├── .gitignore ├── Harness Projects ├── App.xojo_code ├── Build Automation.xojo_code ├── Examples │ ├── Eddies.xojo_code │ ├── Eddies │ │ ├── Customer.xojo_code │ │ ├── GetCustomer.xojo_code │ │ └── GetCustomerList.xojo_code │ ├── GetCatsMessage.xojo_code │ └── SQLFormatter.xojo_code ├── MainMenuBar.xojo_menu ├── REST Harness.xojo_project ├── REST Harness.xojo_resources └── Windows Folder │ ├── WndCats.xojo_window │ ├── WndEddies.xojo_window │ ├── WndMain.xojo_window │ └── WndSQLFormatter.xojo_window ├── LICENSE.md ├── README.md └── REST Resources ├── M_REST.xojo_code └── M_REST ├── ClassMeta.xojo_code ├── Options.xojo_code ├── PrivateMessage.xojo_code ├── PrivateOptions.xojo_code ├── PrivateSurrogate.xojo_code ├── RESTException.xojo_code ├── RESTMessageSurrogate_MTC.xojo_code ├── RESTMessage_MTC.xojo_code └── TextProvider.xojo_code /.gitignore: -------------------------------------------------------------------------------- 1 | *.xojo_uistate 2 | .vscode 3 | -------------------------------------------------------------------------------- /Harness Projects/App.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class App 3 | Inherits Application 4 | #tag MenuHandler 5 | Function ExamplesCats() As Boolean Handles ExamplesCats.Action 6 | WndCats.Show 7 | Return True 8 | 9 | End Function 10 | #tag EndMenuHandler 11 | 12 | #tag MenuHandler 13 | Function ExamplesEddies() As Boolean Handles ExamplesEddies.Action 14 | WndEddies.Show 15 | Return True 16 | 17 | End Function 18 | #tag EndMenuHandler 19 | 20 | #tag MenuHandler 21 | Function ExamplesSQLFormatter() As Boolean Handles ExamplesSQLFormatter.Action 22 | WndSQLFormatter.Show 23 | Return True 24 | 25 | End Function 26 | #tag EndMenuHandler 27 | 28 | 29 | #tag Constant, Name = kEditClear, Type = String, Dynamic = False, Default = \"&Delete", Scope = Public 30 | #Tag Instance, Platform = Windows, Language = Default, Definition = \"&Delete" 31 | #Tag Instance, Platform = Linux, Language = Default, Definition = \"&Delete" 32 | #tag EndConstant 33 | 34 | #tag Constant, Name = kFileQuit, Type = String, Dynamic = False, Default = \"&Quit", Scope = Public 35 | #Tag Instance, Platform = Windows, Language = Default, Definition = \"E&xit" 36 | #tag EndConstant 37 | 38 | #tag Constant, Name = kFileQuitShortcut, Type = String, Dynamic = False, Default = \"", Scope = Public 39 | #Tag Instance, Platform = Mac OS, Language = Default, Definition = \"Cmd+Q" 40 | #Tag Instance, Platform = Linux, Language = Default, Definition = \"Ctrl+Q" 41 | #tag EndConstant 42 | 43 | 44 | End Class 45 | #tag EndClass 46 | -------------------------------------------------------------------------------- /Harness Projects/Build Automation.xojo_code: -------------------------------------------------------------------------------- 1 | #tag BuildAutomation 2 | Begin BuildStepList Linux 3 | Begin BuildProjectStep Build 4 | End 5 | End 6 | Begin BuildStepList Mac OS X 7 | Begin BuildProjectStep Build 8 | End 9 | End 10 | Begin BuildStepList Windows 11 | Begin BuildProjectStep Build 12 | End 13 | End 14 | #tag EndBuildAutomation 15 | -------------------------------------------------------------------------------- /Harness Projects/Examples/Eddies.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Module 2 | Protected Module Eddies 3 | #tag Constant, Name = kBaseURL, Type = Text, Dynamic = False, Default = \"http://demos.xojo.com/EEWS/index.cgi/api/", Scope = Private 4 | #tag EndConstant 5 | 6 | 7 | #tag ViewBehavior 8 | #tag ViewProperty 9 | Name="Index" 10 | Visible=true 11 | Group="ID" 12 | InitialValue="-2147483648" 13 | Type="Integer" 14 | #tag EndViewProperty 15 | #tag ViewProperty 16 | Name="Left" 17 | Visible=true 18 | Group="Position" 19 | InitialValue="0" 20 | Type="Integer" 21 | #tag EndViewProperty 22 | #tag ViewProperty 23 | Name="Name" 24 | Visible=true 25 | Group="ID" 26 | Type="String" 27 | #tag EndViewProperty 28 | #tag ViewProperty 29 | Name="Super" 30 | Visible=true 31 | Group="ID" 32 | Type="String" 33 | #tag EndViewProperty 34 | #tag ViewProperty 35 | Name="Top" 36 | Visible=true 37 | Group="Position" 38 | InitialValue="0" 39 | Type="Integer" 40 | #tag EndViewProperty 41 | #tag EndViewBehavior 42 | End Module 43 | #tag EndModule 44 | -------------------------------------------------------------------------------- /Harness Projects/Examples/Eddies/Customer.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class Customer 3 | #tag Property, Flags = &h0 4 | City As Text 5 | #tag EndProperty 6 | 7 | #tag Property, Flags = &h0 8 | Email As Text 9 | #tag EndProperty 10 | 11 | #tag Property, Flags = &h0 12 | FirstName As Text 13 | #tag EndProperty 14 | 15 | #tag Property, Flags = &h0 16 | ID As Text 17 | #tag EndProperty 18 | 19 | #tag Property, Flags = &h0 20 | LastName As Text 21 | #tag EndProperty 22 | 23 | #tag Property, Flags = &h0 24 | Phone As Text 25 | #tag EndProperty 26 | 27 | #tag Property, Flags = &h0 28 | Photo As Picture 29 | #tag EndProperty 30 | 31 | #tag Property, Flags = &h0 32 | State As Text 33 | #tag EndProperty 34 | 35 | #tag Property, Flags = &h0 36 | Taxable As Boolean 37 | #tag EndProperty 38 | 39 | #tag Property, Flags = &h0 40 | Zip As Text 41 | #tag EndProperty 42 | 43 | 44 | #tag ViewBehavior 45 | #tag ViewProperty 46 | Name="City" 47 | Group="Behavior" 48 | Type="Text" 49 | #tag EndViewProperty 50 | #tag ViewProperty 51 | Name="Email" 52 | Group="Behavior" 53 | Type="Text" 54 | #tag EndViewProperty 55 | #tag ViewProperty 56 | Name="FirstName" 57 | Group="Behavior" 58 | Type="Text" 59 | #tag EndViewProperty 60 | #tag ViewProperty 61 | Name="ID" 62 | Group="Behavior" 63 | Type="Text" 64 | #tag EndViewProperty 65 | #tag ViewProperty 66 | Name="Index" 67 | Visible=true 68 | Group="ID" 69 | InitialValue="-2147483648" 70 | Type="Integer" 71 | #tag EndViewProperty 72 | #tag ViewProperty 73 | Name="LastName" 74 | Group="Behavior" 75 | Type="Text" 76 | #tag EndViewProperty 77 | #tag ViewProperty 78 | Name="Left" 79 | Visible=true 80 | Group="Position" 81 | InitialValue="0" 82 | Type="Integer" 83 | #tag EndViewProperty 84 | #tag ViewProperty 85 | Name="Name" 86 | Visible=true 87 | Group="ID" 88 | Type="String" 89 | #tag EndViewProperty 90 | #tag ViewProperty 91 | Name="Phone" 92 | Group="Behavior" 93 | Type="Text" 94 | #tag EndViewProperty 95 | #tag ViewProperty 96 | Name="Photo" 97 | Group="Behavior" 98 | Type="Picture" 99 | #tag EndViewProperty 100 | #tag ViewProperty 101 | Name="State" 102 | Group="Behavior" 103 | Type="Text" 104 | #tag EndViewProperty 105 | #tag ViewProperty 106 | Name="Super" 107 | Visible=true 108 | Group="ID" 109 | Type="String" 110 | #tag EndViewProperty 111 | #tag ViewProperty 112 | Name="Taxable" 113 | Group="Behavior" 114 | Type="Boolean" 115 | #tag EndViewProperty 116 | #tag ViewProperty 117 | Name="Top" 118 | Visible=true 119 | Group="Position" 120 | InitialValue="0" 121 | Type="Integer" 122 | #tag EndViewProperty 123 | #tag ViewProperty 124 | Name="Zip" 125 | Group="Behavior" 126 | Type="Text" 127 | #tag EndViewProperty 128 | #tag EndViewBehavior 129 | End Class 130 | #tag EndClass 131 | -------------------------------------------------------------------------------- /Harness Projects/Examples/Eddies/GetCustomer.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class GetCustomer 3 | Inherits RESTMessage_MTC 4 | #tag Event 5 | Function GetRESTType() As RESTTypes 6 | return RESTTypes.POST 7 | End Function 8 | #tag EndEvent 9 | 10 | #tag Event 11 | Function GetURLPattern() As Text 12 | return kBaseURL + "GetCustomer" 13 | End Function 14 | #tag EndEvent 15 | 16 | #tag Event 17 | Function IncomingPayloadValueToProperty(value As Auto, prop As Xojo.Introspection.PropertyInfo, hostObject As Object) As Boolean 18 | if hostObject isa Customer then 19 | 20 | if prop.Name = "Photo" then 21 | dim textData as text = value 22 | dim binaryData as MemoryBlock = DecodeBase64( textData ) 23 | dim p as Picture = Picture.FromData( binaryData ) 24 | prop.Value( hostObject ) = p 25 | return true 26 | 27 | elseif prop.Name = "Taxable" then 28 | dim b as boolean = value = "1" 29 | prop.Value( hostObject ) = b 30 | return true 31 | 32 | end if 33 | 34 | end if 35 | End Function 36 | #tag EndEvent 37 | 38 | 39 | #tag Property, Flags = &h0 40 | ID As Text 41 | #tag EndProperty 42 | 43 | #tag Property, Flags = &h0 44 | ReturnGetCustomer As Customer 45 | #tag EndProperty 46 | 47 | 48 | #tag ViewBehavior 49 | #tag ViewProperty 50 | Name="DefaultRESTType" 51 | Visible=true 52 | Group="Behavior" 53 | InitialValue="RESTTypes.Unknown" 54 | Type="RESTTypes" 55 | EditorType="Enum" 56 | #tag EnumValues 57 | "0 - Unknown" 58 | "1 - Create" 59 | "2 - Read" 60 | "3 - UpdateReplace" 61 | "4 - UpdateModify" 62 | "5 - Authenticate" 63 | "6 - DELETE" 64 | "7 - GET" 65 | "8 - HEAD" 66 | "9 - OPTIONS" 67 | "10 - PATCH" 68 | "11 - POST" 69 | "12 - PUT" 70 | #tag EndEnumValues 71 | #tag EndViewProperty 72 | #tag ViewProperty 73 | Name="ID" 74 | Group="Behavior" 75 | Type="Text" 76 | #tag EndViewProperty 77 | #tag ViewProperty 78 | Name="Index" 79 | Visible=true 80 | Group="ID" 81 | InitialValue="-2147483648" 82 | Type="Integer" 83 | #tag EndViewProperty 84 | #tag ViewProperty 85 | Name="IsConnected" 86 | Group="Behavior" 87 | Type="Boolean" 88 | #tag EndViewProperty 89 | #tag ViewProperty 90 | Name="Left" 91 | Visible=true 92 | Group="Position" 93 | InitialValue="0" 94 | Type="Integer" 95 | #tag EndViewProperty 96 | #tag ViewProperty 97 | Name="MessageSerialNumber" 98 | Group="Behavior" 99 | Type="Int64" 100 | #tag EndViewProperty 101 | #tag ViewProperty 102 | Name="Name" 103 | Visible=true 104 | Group="ID" 105 | Type="String" 106 | #tag EndViewProperty 107 | #tag ViewProperty 108 | Name="RESTType" 109 | Group="Behavior" 110 | Type="RESTTypes" 111 | EditorType="Enum" 112 | #tag EnumValues 113 | "0 - Unknown" 114 | "1 - Create" 115 | "2 - Read" 116 | "3 - UpdateReplace" 117 | "4 - UpdateModify" 118 | "5 - Authenticate" 119 | "6 - DELETE" 120 | "7 - GET" 121 | "8 - HEAD" 122 | "9 - OPTIONS" 123 | "10 - PATCH" 124 | "11 - POST" 125 | "12 - PUT" 126 | #tag EndEnumValues 127 | #tag EndViewProperty 128 | #tag ViewProperty 129 | Name="RoundTripMs" 130 | Group="Behavior" 131 | Type="Double" 132 | #tag EndViewProperty 133 | #tag ViewProperty 134 | Name="RoundTripWithProcessingMs" 135 | Group="Behavior" 136 | Type="Double" 137 | #tag EndViewProperty 138 | #tag ViewProperty 139 | Name="Super" 140 | Visible=true 141 | Group="ID" 142 | Type="String" 143 | #tag EndViewProperty 144 | #tag ViewProperty 145 | Name="Top" 146 | Visible=true 147 | Group="Position" 148 | InitialValue="0" 149 | Type="Integer" 150 | #tag EndViewProperty 151 | #tag ViewProperty 152 | Name="ValidateCertificates" 153 | Visible=true 154 | Group="Behavior" 155 | Type="Boolean" 156 | #tag EndViewProperty 157 | #tag EndViewBehavior 158 | End Class 159 | #tag EndClass 160 | -------------------------------------------------------------------------------- /Harness Projects/Examples/Eddies/GetCustomerList.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class GetCustomerList 3 | Inherits RESTMessage_MTC 4 | #tag Event 5 | Function GetRESTType() As RESTTypes 6 | return RESTTypes.GET 7 | End Function 8 | #tag EndEvent 9 | 10 | #tag Event 11 | Function GetURLPattern() As Text 12 | return kBaseURL + "GetAllCustomers" 13 | End Function 14 | #tag EndEvent 15 | 16 | 17 | #tag Property, Flags = &h0 18 | ReturnGetAllCustomers As Xojo.Core.Dictionary 19 | #tag EndProperty 20 | 21 | 22 | #tag ViewBehavior 23 | #tag ViewProperty 24 | Name="DefaultRESTType" 25 | Visible=true 26 | Group="Behavior" 27 | InitialValue="RESTTypes.Unknown" 28 | Type="RESTTypes" 29 | EditorType="Enum" 30 | #tag EnumValues 31 | "0 - Unknown" 32 | "1 - Create" 33 | "2 - Read" 34 | "3 - UpdateReplace" 35 | "4 - UpdateModify" 36 | "5 - Authenticate" 37 | "6 - DELETE" 38 | "7 - GET" 39 | "8 - HEAD" 40 | "9 - OPTIONS" 41 | "10 - PATCH" 42 | "11 - POST" 43 | "12 - PUT" 44 | #tag EndEnumValues 45 | #tag EndViewProperty 46 | #tag ViewProperty 47 | Name="Index" 48 | Visible=true 49 | Group="ID" 50 | InitialValue="-2147483648" 51 | Type="Integer" 52 | #tag EndViewProperty 53 | #tag ViewProperty 54 | Name="IsConnected" 55 | Group="Behavior" 56 | Type="Boolean" 57 | #tag EndViewProperty 58 | #tag ViewProperty 59 | Name="Left" 60 | Visible=true 61 | Group="Position" 62 | InitialValue="0" 63 | Type="Integer" 64 | #tag EndViewProperty 65 | #tag ViewProperty 66 | Name="MessageSerialNumber" 67 | Group="Behavior" 68 | Type="Int64" 69 | #tag EndViewProperty 70 | #tag ViewProperty 71 | Name="Name" 72 | Visible=true 73 | Group="ID" 74 | Type="String" 75 | #tag EndViewProperty 76 | #tag ViewProperty 77 | Name="RESTType" 78 | Group="Behavior" 79 | Type="RESTTypes" 80 | EditorType="Enum" 81 | #tag EnumValues 82 | "0 - Unknown" 83 | "1 - Create" 84 | "2 - Read" 85 | "3 - UpdateReplace" 86 | "4 - UpdateModify" 87 | "5 - Authenticate" 88 | "6 - DELETE" 89 | "7 - GET" 90 | "8 - HEAD" 91 | "9 - OPTIONS" 92 | "10 - PATCH" 93 | "11 - POST" 94 | "12 - PUT" 95 | #tag EndEnumValues 96 | #tag EndViewProperty 97 | #tag ViewProperty 98 | Name="RoundTripMs" 99 | Group="Behavior" 100 | Type="Double" 101 | #tag EndViewProperty 102 | #tag ViewProperty 103 | Name="RoundTripWithProcessingMs" 104 | Group="Behavior" 105 | Type="Double" 106 | #tag EndViewProperty 107 | #tag ViewProperty 108 | Name="Super" 109 | Visible=true 110 | Group="ID" 111 | Type="String" 112 | #tag EndViewProperty 113 | #tag ViewProperty 114 | Name="Top" 115 | Visible=true 116 | Group="Position" 117 | InitialValue="0" 118 | Type="Integer" 119 | #tag EndViewProperty 120 | #tag ViewProperty 121 | Name="ValidateCertificates" 122 | Visible=true 123 | Group="Behavior" 124 | Type="Boolean" 125 | #tag EndViewProperty 126 | #tag EndViewBehavior 127 | End Class 128 | #tag EndClass 129 | -------------------------------------------------------------------------------- /Harness Projects/Examples/GetCatsMessage.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class GetCatsMessage 3 | Inherits RESTMessage_MTC 4 | #tag Event 5 | Function GetRESTType() As RESTTypes 6 | return RESTTypes.GET 7 | End Function 8 | #tag EndEvent 9 | 10 | #tag Event 11 | Function GetURLPattern() As Text 12 | return "http://thecatapi.com/api/images/get?format=:Format&results_per_page=:ResultsPerPage&size=:Size&type=:Type" 13 | 14 | End Function 15 | #tag EndEvent 16 | 17 | 18 | #tag Property, Flags = &h0 19 | Format As Text = "src" 20 | #tag EndProperty 21 | 22 | #tag Property, Flags = &h0 23 | ResultsPerPage As Integer = 1 24 | #tag EndProperty 25 | 26 | #tag Property, Flags = &h0 27 | ReturnPicture As Picture 28 | #tag EndProperty 29 | 30 | #tag Property, Flags = &h0 31 | Size As Text = "full" 32 | #tag EndProperty 33 | 34 | #tag Property, Flags = &h0 35 | Type As Text = "png" 36 | #tag EndProperty 37 | 38 | 39 | #tag ViewBehavior 40 | #tag ViewProperty 41 | Name="DefaultRESTType" 42 | Visible=true 43 | Group="Behavior" 44 | InitialValue="RESTTypes.Unknown" 45 | Type="RESTTypes" 46 | EditorType="Enum" 47 | #tag EnumValues 48 | "0 - Unknown" 49 | "1 - Create" 50 | "2 - Read" 51 | "3 - UpdateReplace" 52 | "4 - UpdateModify" 53 | "5 - Authenticate" 54 | "6 - DELETE" 55 | "7 - GET" 56 | "8 - HEAD" 57 | "9 - OPTIONS" 58 | "10 - PATCH" 59 | "11 - POST" 60 | "12 - PUT" 61 | #tag EndEnumValues 62 | #tag EndViewProperty 63 | #tag ViewProperty 64 | Name="Format" 65 | Visible=true 66 | Group="Behavior" 67 | InitialValue="src" 68 | Type="Text" 69 | #tag EndViewProperty 70 | #tag ViewProperty 71 | Name="Index" 72 | Visible=true 73 | Group="ID" 74 | InitialValue="-2147483648" 75 | Type="Integer" 76 | #tag EndViewProperty 77 | #tag ViewProperty 78 | Name="IsConnected" 79 | Group="Behavior" 80 | Type="Boolean" 81 | #tag EndViewProperty 82 | #tag ViewProperty 83 | Name="Left" 84 | Visible=true 85 | Group="Position" 86 | InitialValue="0" 87 | Type="Integer" 88 | #tag EndViewProperty 89 | #tag ViewProperty 90 | Name="MessageSerialNumber" 91 | Group="Behavior" 92 | Type="Int64" 93 | #tag EndViewProperty 94 | #tag ViewProperty 95 | Name="Name" 96 | Visible=true 97 | Group="ID" 98 | Type="String" 99 | #tag EndViewProperty 100 | #tag ViewProperty 101 | Name="RESTType" 102 | Group="Behavior" 103 | Type="RESTTypes" 104 | EditorType="Enum" 105 | #tag EnumValues 106 | "0 - Unknown" 107 | "1 - Create" 108 | "2 - Read" 109 | "3 - UpdateReplace" 110 | "4 - UpdateModify" 111 | "5 - Authenticate" 112 | "6 - DELETE" 113 | "7 - GET" 114 | "8 - HEAD" 115 | "9 - OPTIONS" 116 | "10 - PATCH" 117 | "11 - POST" 118 | "12 - PUT" 119 | #tag EndEnumValues 120 | #tag EndViewProperty 121 | #tag ViewProperty 122 | Name="ResultsPerPage" 123 | Visible=true 124 | Group="Behavior" 125 | InitialValue="1" 126 | Type="Integer" 127 | #tag EndViewProperty 128 | #tag ViewProperty 129 | Name="ReturnPicture" 130 | Group="Behavior" 131 | Type="Picture" 132 | #tag EndViewProperty 133 | #tag ViewProperty 134 | Name="RoundTripMs" 135 | Group="Behavior" 136 | Type="Double" 137 | #tag EndViewProperty 138 | #tag ViewProperty 139 | Name="RoundTripWithProcessingMs" 140 | Group="Behavior" 141 | Type="Double" 142 | #tag EndViewProperty 143 | #tag ViewProperty 144 | Name="Size" 145 | Visible=true 146 | Group="Behavior" 147 | InitialValue="full" 148 | Type="Text" 149 | #tag EndViewProperty 150 | #tag ViewProperty 151 | Name="Super" 152 | Visible=true 153 | Group="ID" 154 | Type="String" 155 | #tag EndViewProperty 156 | #tag ViewProperty 157 | Name="Top" 158 | Visible=true 159 | Group="Position" 160 | InitialValue="0" 161 | Type="Integer" 162 | #tag EndViewProperty 163 | #tag ViewProperty 164 | Name="Type" 165 | Visible=true 166 | Group="Behavior" 167 | InitialValue="jpg" 168 | Type="Text" 169 | #tag EndViewProperty 170 | #tag ViewProperty 171 | Name="ValidateCertificates" 172 | Visible=true 173 | Group="Behavior" 174 | Type="Boolean" 175 | #tag EndViewProperty 176 | #tag EndViewBehavior 177 | End Class 178 | #tag EndClass 179 | -------------------------------------------------------------------------------- /Harness Projects/Examples/SQLFormatter.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class SQLFormatter 3 | Inherits RESTMessage_MTC 4 | #tag Event 5 | Function CancelSend(ByRef url As Text, ByRef httpAction As Text, ByRef payload As Xojo.Core.MemoryBlock, ByRef payloadMIMEType As Text) As Boolean 6 | #pragma unused url 7 | #pragma unused httpAction 8 | 9 | payloadMIMEType = "application/x-www-form-urlencoded" 10 | 11 | dim postText As text = "rqst_input_sql=" + EncodeURLComponent( InputSQL ).ToText + _ 12 | "&rqst_db_vendor=" + DBVendor.ToText 13 | 14 | payload = Xojo.Core.TextEncoding.UTF8.ConvertTextToData(postText) 15 | 16 | End Function 17 | #tag EndEvent 18 | 19 | #tag Event 20 | Function GetRESTType() As RESTTypes 21 | return RESTTypes.POST 22 | End Function 23 | #tag EndEvent 24 | 25 | #tag Event 26 | Function GetURLPattern() As Text 27 | return "http://www.gudusoft.com/format.php" 28 | End Function 29 | #tag EndEvent 30 | 31 | #tag Event 32 | Sub Setup() 33 | MessageOptions.SendWithPayloadIfAvailable = false // We'll handle it ourselves 34 | MessageOptions.ReturnPropertyPrefix = "" 35 | DBVendor = 1 36 | 37 | End Sub 38 | #tag EndEvent 39 | 40 | 41 | #tag Property, Flags = &h0 42 | DBVendor As Integer = 1 43 | #tag EndProperty 44 | 45 | #tag Property, Flags = &h0 46 | InputSQL As Text 47 | #tag EndProperty 48 | 49 | #tag Property, Flags = &h0 50 | Rspn_Formatted_SQL As Text 51 | #tag EndProperty 52 | 53 | 54 | #tag ViewBehavior 55 | #tag ViewProperty 56 | Name="DBVendor" 57 | Visible=true 58 | Group="Behavior" 59 | InitialValue="1" 60 | Type="Integer" 61 | #tag EndViewProperty 62 | #tag ViewProperty 63 | Name="DefaultRESTType" 64 | Visible=true 65 | Group="Behavior" 66 | InitialValue="RESTTypes.Unknown" 67 | Type="RESTTypes" 68 | EditorType="Enum" 69 | #tag EnumValues 70 | "0 - Unknown" 71 | "1 - Create" 72 | "2 - Read" 73 | "3 - UpdateReplace" 74 | "4 - UpdateModify" 75 | "5 - Authenticate" 76 | "6 - DELETE" 77 | "7 - GET" 78 | "8 - HEAD" 79 | "9 - OPTIONS" 80 | "10 - PATCH" 81 | "11 - POST" 82 | "12 - PUT" 83 | #tag EndEnumValues 84 | #tag EndViewProperty 85 | #tag ViewProperty 86 | Name="Index" 87 | Visible=true 88 | Group="ID" 89 | InitialValue="-2147483648" 90 | Type="Integer" 91 | #tag EndViewProperty 92 | #tag ViewProperty 93 | Name="InputSQL" 94 | Group="Behavior" 95 | Type="Text" 96 | #tag EndViewProperty 97 | #tag ViewProperty 98 | Name="IsConnected" 99 | Group="Behavior" 100 | Type="Boolean" 101 | #tag EndViewProperty 102 | #tag ViewProperty 103 | Name="Left" 104 | Visible=true 105 | Group="Position" 106 | InitialValue="0" 107 | Type="Integer" 108 | #tag EndViewProperty 109 | #tag ViewProperty 110 | Name="MessageSerialNumber" 111 | Group="Behavior" 112 | Type="Int64" 113 | #tag EndViewProperty 114 | #tag ViewProperty 115 | Name="Name" 116 | Visible=true 117 | Group="ID" 118 | Type="String" 119 | #tag EndViewProperty 120 | #tag ViewProperty 121 | Name="RESTType" 122 | Group="Behavior" 123 | Type="RESTTypes" 124 | EditorType="Enum" 125 | #tag EnumValues 126 | "0 - Unknown" 127 | "1 - Create" 128 | "2 - Read" 129 | "3 - UpdateReplace" 130 | "4 - UpdateModify" 131 | "5 - Authenticate" 132 | "6 - DELETE" 133 | "7 - GET" 134 | "8 - HEAD" 135 | "9 - OPTIONS" 136 | "10 - PATCH" 137 | "11 - POST" 138 | "12 - PUT" 139 | #tag EndEnumValues 140 | #tag EndViewProperty 141 | #tag ViewProperty 142 | Name="RoundTripMs" 143 | Group="Behavior" 144 | Type="Double" 145 | #tag EndViewProperty 146 | #tag ViewProperty 147 | Name="RoundTripWithProcessingMs" 148 | Group="Behavior" 149 | Type="Double" 150 | #tag EndViewProperty 151 | #tag ViewProperty 152 | Name="Rspn_Formatted_SQL" 153 | Group="Behavior" 154 | Type="Text" 155 | #tag EndViewProperty 156 | #tag ViewProperty 157 | Name="Super" 158 | Visible=true 159 | Group="ID" 160 | Type="String" 161 | #tag EndViewProperty 162 | #tag ViewProperty 163 | Name="Top" 164 | Visible=true 165 | Group="Position" 166 | InitialValue="0" 167 | Type="Integer" 168 | #tag EndViewProperty 169 | #tag ViewProperty 170 | Name="ValidateCertificates" 171 | Visible=true 172 | Group="Behavior" 173 | Type="Boolean" 174 | #tag EndViewProperty 175 | #tag EndViewBehavior 176 | End Class 177 | #tag EndClass 178 | -------------------------------------------------------------------------------- /Harness Projects/MainMenuBar.xojo_menu: -------------------------------------------------------------------------------- 1 | #tag Menu 2 | Begin Menu MainMenuBar 3 | Begin MenuItem FileMenu 4 | SpecialMenu = 0 5 | Text = "&File" 6 | Index = -2147483648 7 | AutoEnable = True 8 | Visible = True 9 | Begin QuitMenuItem FileQuit 10 | SpecialMenu = 0 11 | Text = "#App.kFileQuit" 12 | Index = -2147483648 13 | ShortcutKey = "#App.kFileQuitShortcut" 14 | Shortcut = "#App.kFileQuitShortcut" 15 | AutoEnable = True 16 | Visible = True 17 | End 18 | End 19 | Begin MenuItem EditMenu 20 | SpecialMenu = 0 21 | Text = "&Edit" 22 | Index = -2147483648 23 | AutoEnable = True 24 | Visible = True 25 | Begin MenuItem EditUndo 26 | SpecialMenu = 0 27 | Text = "&Undo" 28 | Index = -2147483648 29 | ShortcutKey = "Z" 30 | Shortcut = "Cmd+Z" 31 | MenuModifier = True 32 | AutoEnable = True 33 | Visible = True 34 | End 35 | Begin MenuItem EditSeparator1 36 | SpecialMenu = 0 37 | Text = "-" 38 | Index = -2147483648 39 | AutoEnable = True 40 | Visible = True 41 | End 42 | Begin MenuItem EditCut 43 | SpecialMenu = 0 44 | Text = "Cu&t" 45 | Index = -2147483648 46 | ShortcutKey = "X" 47 | Shortcut = "Cmd+X" 48 | MenuModifier = True 49 | AutoEnable = True 50 | Visible = True 51 | End 52 | Begin MenuItem EditCopy 53 | SpecialMenu = 0 54 | Text = "&Copy" 55 | Index = -2147483648 56 | ShortcutKey = "C" 57 | Shortcut = "Cmd+C" 58 | MenuModifier = True 59 | AutoEnable = True 60 | Visible = True 61 | End 62 | Begin MenuItem EditPaste 63 | SpecialMenu = 0 64 | Text = "&Paste" 65 | Index = -2147483648 66 | ShortcutKey = "V" 67 | Shortcut = "Cmd+V" 68 | MenuModifier = True 69 | AutoEnable = True 70 | Visible = True 71 | End 72 | Begin MenuItem EditClear 73 | SpecialMenu = 0 74 | Text = "#App.kEditClear" 75 | Index = -2147483648 76 | AutoEnable = True 77 | Visible = True 78 | End 79 | Begin MenuItem EditSeparator2 80 | SpecialMenu = 0 81 | Text = "-" 82 | Index = -2147483648 83 | AutoEnable = True 84 | Visible = True 85 | End 86 | Begin MenuItem EditSelectAll 87 | SpecialMenu = 0 88 | Text = "Select &All" 89 | Index = -2147483648 90 | ShortcutKey = "A" 91 | Shortcut = "Cmd+A" 92 | MenuModifier = True 93 | AutoEnable = True 94 | Visible = True 95 | End 96 | End 97 | Begin MenuItem ExamplesMenu 98 | SpecialMenu = 0 99 | Text = "Examples" 100 | Index = -2147483648 101 | AutoEnable = True 102 | Visible = True 103 | Begin MenuItem ExamplesCats 104 | SpecialMenu = 0 105 | Text = "Cats" 106 | Index = -2147483648 107 | AutoEnable = True 108 | Visible = True 109 | End 110 | Begin MenuItem ExamplesEddies 111 | SpecialMenu = 0 112 | Text = "Eddie's Electronics" 113 | Index = -2147483648 114 | AutoEnable = True 115 | Visible = True 116 | End 117 | Begin MenuItem ExamplesSQLFormatter 118 | SpecialMenu = 0 119 | Text = "SQL Formatter" 120 | Index = -2147483648 121 | AutoEnable = True 122 | Visible = True 123 | End 124 | End 125 | End 126 | #tag EndMenu 127 | -------------------------------------------------------------------------------- /Harness Projects/REST Harness.xojo_project: -------------------------------------------------------------------------------- 1 | Type=Desktop 2 | RBProjectVersion=2016.011 3 | MinIDEVersion=20070100 4 | Class=App;App.xojo_code;&h1EC067FF;&h0;false 5 | MenuBar=MainMenuBar;MainMenuBar.xojo_menu;&h5FF8CFFF;&h0;false 6 | BuildSteps=Build Automation;Build Automation.xojo_code;&h3B4A37FF;&h0;false 7 | Module=M_REST;../REST Resources/M_REST.xojo_code;&h608AF7FF;&hF907FFF;false 8 | Class=Options;../REST Resources/M_REST/Options.xojo_code;&h37BAA7FF;&h608AF7FF;false 9 | Class=RESTException;../REST Resources/M_REST/RESTException.xojo_code;&h394E8FFF;&h608AF7FF;false 10 | Class=RESTMessage_MTC;../REST Resources/M_REST/RESTMessage_MTC.xojo_code;&h109DCFFF;&h608AF7FF;false 11 | Class=RESTMessageSurrogate_MTC;../REST Resources/M_REST/RESTMessageSurrogate_MTC.xojo_code;&h677777FF;&h608AF7FF;false 12 | Interface=TextProvider;../REST Resources/M_REST/TextProvider.xojo_code;&h1F1CC7FF;&h608AF7FF;false 13 | Class=ClassMeta;../REST Resources/M_REST/ClassMeta.xojo_code;&h5961FFF;&h608AF7FF;false 14 | Folder=Examples;Examples;&h51D0A7FF;&h0;false 15 | Module=Eddies;Examples/Eddies.xojo_code;&h5784FFFF;&h51D0A7FF;false 16 | Class=GetCatsMessage;Examples/GetCatsMessage.xojo_code;&h5EC0D7FF;&h51D0A7FF;false 17 | Interface=PrivateMessage;../REST Resources/M_REST/PrivateMessage.xojo_code;&h6F4757FF;&h608AF7FF;false 18 | Interface=PrivateOptions;../REST Resources/M_REST/PrivateOptions.xojo_code;&h7E44C7FF;&h608AF7FF;false 19 | Class=SQLFormatter;Examples/SQLFormatter.xojo_code;&h64EFFFF;&h51D0A7FF;false 20 | Folder=Windows Folder;Windows Folder;&h6FA08FFF;&h0;false 21 | Window=WndMain;Windows Folder/WndMain.xojo_window;&h8156FFF;&h6FA08FFF;false 22 | Folder=REST Resources;../REST Resources;&hF907FFF;&h0;false 23 | Window=WndCats;Windows Folder/WndCats.xojo_window;&h26C787FF;&h6FA08FFF;false 24 | Window=WndEddies;Windows Folder/WndEddies.xojo_window;&h104087FF;&h6FA08FFF;false 25 | Window=WndSQLFormatter;Windows Folder/WndSQLFormatter.xojo_window;&h79F357FF;&h6FA08FFF;false 26 | Class=GetCustomerList;Examples/Eddies/GetCustomerList.xojo_code;&h54E4DFFF;&h5784FFFF;false 27 | Class=GetCustomer;Examples/Eddies/GetCustomer.xojo_code;&h6C67FFFF;&h5784FFFF;false 28 | Class=Customer;Examples/Eddies/Customer.xojo_code;&h7E394FFF;&h5784FFFF;false 29 | Interface=PrivateSurrogate;../REST Resources/M_REST/PrivateSurrogate.xojo_code;&h25EB87FF;&h608AF7FF;false 30 | DefaultWindow=WndMain 31 | AppMenuBar=MainMenuBar 32 | MajorVersion=1 33 | MinorVersion=0 34 | SubVersion=0 35 | NonRelease=0 36 | Release=0 37 | InfoVersion= 38 | LongVersion= 39 | ShortVersion= 40 | WinCompanyName=MacTechnologies Consulting 41 | WinInternalName= 42 | WinProductName= 43 | WinFileDescription= 44 | AutoIncrementVersionInformation=False 45 | BuildFlags=&h4900 46 | BuildLanguage=&h0 47 | DebugLanguage=&h0 48 | Region= 49 | WindowsName=REST Harness.exe 50 | MacCarbonMachName=REST Harness 51 | LinuxX86Name=REST Harness 52 | MacCreator= 53 | MDI=0 54 | MDICaption= 55 | DefaultEncoding=&h0 56 | AppIcon=REST Harness.xojo_resources;&h0 57 | OSXBundleID=com.mactechnologiesconsulting.restharness 58 | DebuggerCommandLine= 59 | UseGDIPlus=False 60 | UseBuildsFolder=True 61 | IsWebProject=False 62 | -------------------------------------------------------------------------------- /Harness Projects/REST Harness.xojo_resources: -------------------------------------------------------------------------------- 1 | ICNS -------------------------------------------------------------------------------- /Harness Projects/Windows Folder/WndCats.xojo_window: -------------------------------------------------------------------------------- 1 | #tag Window 2 | Begin Window WndCats 3 | BackColor = &cFFFFFF00 4 | Backdrop = 0 5 | CloseButton = True 6 | Compatibility = "" 7 | Composite = False 8 | Frame = 0 9 | FullScreen = False 10 | FullScreenButton= False 11 | HasBackColor = False 12 | Height = 400 13 | ImplicitInstance= True 14 | LiveResize = True 15 | MacProcID = 0 16 | MaxHeight = 32000 17 | MaximizeButton = True 18 | MaxWidth = 32000 19 | MenuBar = 1610141695 20 | MenuBarVisible = True 21 | MinHeight = 400 22 | MinimizeButton = True 23 | MinWidth = 600 24 | Placement = 0 25 | Resizeable = True 26 | Title = "Cats" 27 | Visible = True 28 | Width = 600 29 | Begin GetCatsMessage msgGetCats 30 | DefaultRESTType = "7" 31 | Enabled = True 32 | Format = "src" 33 | Index = -2147483648 34 | IsConnected = False 35 | LockedInPosition= False 36 | MessageSerialNumber= "" 37 | RESTType = "7" 38 | ResultsPerPage = 1 39 | ReturnPicture = 0 40 | RoundTripMs = 0.0 41 | RoundTripWithProcessingMs= 0.0 42 | Scope = 2 43 | Size = "full" 44 | TabPanelIndex = 0 45 | Type = "png" 46 | ValidateCertificates= False 47 | End 48 | Begin PushButton btnGetCat 49 | AutoDeactivate = True 50 | Bold = False 51 | ButtonStyle = "0" 52 | Cancel = False 53 | Caption = "Get Cat" 54 | Default = False 55 | Enabled = True 56 | Height = 20 57 | HelpTag = "" 58 | Index = -2147483648 59 | InitialParent = "" 60 | Italic = False 61 | Left = 20 62 | LockBottom = False 63 | LockedInPosition= False 64 | LockLeft = True 65 | LockRight = False 66 | LockTop = True 67 | Scope = 2 68 | TabIndex = 0 69 | TabPanelIndex = 0 70 | TabStop = True 71 | TextFont = "System" 72 | TextSize = 0.0 73 | TextUnit = 0 74 | Top = 20 75 | Underline = False 76 | Visible = True 77 | Width = 80 78 | End 79 | Begin Canvas cvsPic 80 | AcceptFocus = False 81 | AcceptTabs = False 82 | AutoDeactivate = True 83 | Backdrop = 0 84 | DoubleBuffer = False 85 | Enabled = True 86 | EraseBackground = True 87 | Height = 328 88 | HelpTag = "" 89 | Index = -2147483648 90 | InitialParent = "" 91 | Left = 20 92 | LockBottom = True 93 | LockedInPosition= False 94 | LockLeft = True 95 | LockRight = True 96 | LockTop = True 97 | Scope = 2 98 | TabIndex = 1 99 | TabPanelIndex = 0 100 | TabStop = True 101 | Top = 52 102 | Transparent = True 103 | UseFocusRing = True 104 | Visible = True 105 | Width = 560 106 | End 107 | End 108 | #tag EndWindow 109 | 110 | #tag WindowCode 111 | #tag Property, Flags = &h21 112 | Private CatPic As Picture 113 | #tag EndProperty 114 | 115 | 116 | #tag EndWindowCode 117 | 118 | #tag Events msgGetCats 119 | #tag Event 120 | Sub ResponseReceived(url As Text, httpStatus As Integer, payload As Auto) 121 | #pragma unused url 122 | #pragma unused httpStatus 123 | #pragma unused payload 124 | 125 | cvsPic.Invalidate 126 | return 127 | 128 | End Sub 129 | #tag EndEvent 130 | #tag EndEvents 131 | #tag Events btnGetCat 132 | #tag Event 133 | Sub Action() 134 | msgGetCats.Send 135 | End Sub 136 | #tag EndEvent 137 | #tag EndEvents 138 | #tag Events cvsPic 139 | #tag Event 140 | Sub Paint(g As Graphics, areas() As REALbasic.Rect) 141 | #pragma unused areas 142 | 143 | dim catPic as Picture = msgGetCats.ReturnPicture 144 | 145 | if catPic is nil then 146 | 147 | g.ClearRect 0, 0, g.Width, g.Height 148 | 149 | else 150 | 151 | g.DrawPicture catPic, 0, 0, g.Width, g.Height, 0, 0, CatPic.Width, CatPic.Height 152 | 153 | end if 154 | End Sub 155 | #tag EndEvent 156 | #tag EndEvents 157 | #tag ViewBehavior 158 | #tag ViewProperty 159 | Name="BackColor" 160 | Visible=true 161 | Group="Background" 162 | InitialValue="&hFFFFFF" 163 | Type="Color" 164 | #tag EndViewProperty 165 | #tag ViewProperty 166 | Name="Backdrop" 167 | Visible=true 168 | Group="Background" 169 | Type="Picture" 170 | EditorType="Picture" 171 | #tag EndViewProperty 172 | #tag ViewProperty 173 | Name="CloseButton" 174 | Visible=true 175 | Group="Frame" 176 | InitialValue="True" 177 | Type="Boolean" 178 | EditorType="Boolean" 179 | #tag EndViewProperty 180 | #tag ViewProperty 181 | Name="Composite" 182 | Group="OS X (Carbon)" 183 | InitialValue="False" 184 | Type="Boolean" 185 | #tag EndViewProperty 186 | #tag ViewProperty 187 | Name="Frame" 188 | Visible=true 189 | Group="Frame" 190 | InitialValue="0" 191 | Type="Integer" 192 | EditorType="Enum" 193 | #tag EnumValues 194 | "0 - Document" 195 | "1 - Movable Modal" 196 | "2 - Modal Dialog" 197 | "3 - Floating Window" 198 | "4 - Plain Box" 199 | "5 - Shadowed Box" 200 | "6 - Rounded Window" 201 | "7 - Global Floating Window" 202 | "8 - Sheet Window" 203 | "9 - Metal Window" 204 | "11 - Modeless Dialog" 205 | #tag EndEnumValues 206 | #tag EndViewProperty 207 | #tag ViewProperty 208 | Name="FullScreen" 209 | Group="Behavior" 210 | InitialValue="False" 211 | Type="Boolean" 212 | EditorType="Boolean" 213 | #tag EndViewProperty 214 | #tag ViewProperty 215 | Name="FullScreenButton" 216 | Visible=true 217 | Group="Frame" 218 | InitialValue="False" 219 | Type="Boolean" 220 | EditorType="Boolean" 221 | #tag EndViewProperty 222 | #tag ViewProperty 223 | Name="HasBackColor" 224 | Visible=true 225 | Group="Background" 226 | InitialValue="False" 227 | Type="Boolean" 228 | #tag EndViewProperty 229 | #tag ViewProperty 230 | Name="Height" 231 | Visible=true 232 | Group="Size" 233 | InitialValue="400" 234 | Type="Integer" 235 | #tag EndViewProperty 236 | #tag ViewProperty 237 | Name="ImplicitInstance" 238 | Visible=true 239 | Group="Behavior" 240 | InitialValue="True" 241 | Type="Boolean" 242 | EditorType="Boolean" 243 | #tag EndViewProperty 244 | #tag ViewProperty 245 | Name="Interfaces" 246 | Visible=true 247 | Group="ID" 248 | Type="String" 249 | EditorType="String" 250 | #tag EndViewProperty 251 | #tag ViewProperty 252 | Name="LiveResize" 253 | Visible=true 254 | Group="Behavior" 255 | InitialValue="True" 256 | Type="Boolean" 257 | EditorType="Boolean" 258 | #tag EndViewProperty 259 | #tag ViewProperty 260 | Name="MacProcID" 261 | Group="OS X (Carbon)" 262 | InitialValue="0" 263 | Type="Integer" 264 | #tag EndViewProperty 265 | #tag ViewProperty 266 | Name="MaxHeight" 267 | Visible=true 268 | Group="Size" 269 | InitialValue="32000" 270 | Type="Integer" 271 | #tag EndViewProperty 272 | #tag ViewProperty 273 | Name="MaximizeButton" 274 | Visible=true 275 | Group="Frame" 276 | InitialValue="True" 277 | Type="Boolean" 278 | EditorType="Boolean" 279 | #tag EndViewProperty 280 | #tag ViewProperty 281 | Name="MaxWidth" 282 | Visible=true 283 | Group="Size" 284 | InitialValue="32000" 285 | Type="Integer" 286 | #tag EndViewProperty 287 | #tag ViewProperty 288 | Name="MenuBar" 289 | Visible=true 290 | Group="Menus" 291 | Type="MenuBar" 292 | EditorType="MenuBar" 293 | #tag EndViewProperty 294 | #tag ViewProperty 295 | Name="MenuBarVisible" 296 | Group="Behavior" 297 | InitialValue="True" 298 | Type="Boolean" 299 | EditorType="Boolean" 300 | #tag EndViewProperty 301 | #tag ViewProperty 302 | Name="MinHeight" 303 | Visible=true 304 | Group="Size" 305 | InitialValue="64" 306 | Type="Integer" 307 | #tag EndViewProperty 308 | #tag ViewProperty 309 | Name="MinimizeButton" 310 | Visible=true 311 | Group="Frame" 312 | InitialValue="True" 313 | Type="Boolean" 314 | EditorType="Boolean" 315 | #tag EndViewProperty 316 | #tag ViewProperty 317 | Name="MinWidth" 318 | Visible=true 319 | Group="Size" 320 | InitialValue="64" 321 | Type="Integer" 322 | #tag EndViewProperty 323 | #tag ViewProperty 324 | Name="Name" 325 | Visible=true 326 | Group="ID" 327 | Type="String" 328 | EditorType="String" 329 | #tag EndViewProperty 330 | #tag ViewProperty 331 | Name="Placement" 332 | Visible=true 333 | Group="Behavior" 334 | InitialValue="0" 335 | Type="Integer" 336 | EditorType="Enum" 337 | #tag EnumValues 338 | "0 - Default" 339 | "1 - Parent Window" 340 | "2 - Main Screen" 341 | "3 - Parent Window Screen" 342 | "4 - Stagger" 343 | #tag EndEnumValues 344 | #tag EndViewProperty 345 | #tag ViewProperty 346 | Name="Resizeable" 347 | Visible=true 348 | Group="Frame" 349 | InitialValue="True" 350 | Type="Boolean" 351 | EditorType="Boolean" 352 | #tag EndViewProperty 353 | #tag ViewProperty 354 | Name="Super" 355 | Visible=true 356 | Group="ID" 357 | Type="String" 358 | EditorType="String" 359 | #tag EndViewProperty 360 | #tag ViewProperty 361 | Name="Title" 362 | Visible=true 363 | Group="Frame" 364 | InitialValue="Untitled" 365 | Type="String" 366 | #tag EndViewProperty 367 | #tag ViewProperty 368 | Name="Visible" 369 | Visible=true 370 | Group="Behavior" 371 | InitialValue="True" 372 | Type="Boolean" 373 | EditorType="Boolean" 374 | #tag EndViewProperty 375 | #tag ViewProperty 376 | Name="Width" 377 | Visible=true 378 | Group="Size" 379 | InitialValue="600" 380 | Type="Integer" 381 | #tag EndViewProperty 382 | #tag EndViewBehavior 383 | -------------------------------------------------------------------------------- /Harness Projects/Windows Folder/WndEddies.xojo_window: -------------------------------------------------------------------------------- 1 | #tag Window 2 | Begin Window WndEddies 3 | BackColor = &cFFFFFF00 4 | Backdrop = 0 5 | CloseButton = True 6 | Compatibility = "" 7 | Composite = False 8 | Frame = 0 9 | FullScreen = False 10 | FullScreenButton= False 11 | HasBackColor = False 12 | Height = 508 13 | ImplicitInstance= True 14 | LiveResize = True 15 | MacProcID = 0 16 | MaxHeight = 508 17 | MaximizeButton = True 18 | MaxWidth = 758 19 | MenuBar = 0 20 | MenuBarVisible = True 21 | MinHeight = 508 22 | MinimizeButton = True 23 | MinWidth = 758 24 | Placement = 0 25 | Resizeable = True 26 | Title = "Eddies Electronics" 27 | Visible = True 28 | Width = 758 29 | Begin Eddies.GetCustomerList msgGetCustomerList 30 | DefaultRESTType = "RESTTypes.Unknown" 31 | Enabled = True 32 | Index = -2147483648 33 | IsConnected = False 34 | LockedInPosition= False 35 | MessageSerialNumber= "" 36 | RESTType = "" 37 | RoundTripMs = 0.0 38 | RoundTripWithProcessingMs= 0.0 39 | Scope = 2 40 | TabPanelIndex = 0 41 | ValidateCertificates= False 42 | End 43 | Begin Eddies.GetCustomer msgGetCustomer 44 | DefaultRESTType = "RESTTypes.Unknown" 45 | Enabled = True 46 | ID = 0 47 | Index = -2147483648 48 | IsConnected = False 49 | LockedInPosition= False 50 | MessageSerialNumber= "" 51 | RESTType = "" 52 | RoundTripMs = 0.0 53 | RoundTripWithProcessingMs= 0.0 54 | Scope = 2 55 | TabPanelIndex = 0 56 | ValidateCertificates= False 57 | End 58 | Begin Listbox lbCustomers 59 | AutoDeactivate = True 60 | AutoHideScrollbars= True 61 | Bold = False 62 | Border = True 63 | ColumnCount = 2 64 | ColumnsResizable= False 65 | ColumnWidths = "20%" 66 | DataField = "" 67 | DataSource = "" 68 | DefaultRowHeight= -1 69 | Enabled = True 70 | EnableDrag = False 71 | EnableDragReorder= False 72 | GridLinesHorizontal= 0 73 | GridLinesVertical= 0 74 | HasHeading = True 75 | HeadingIndex = -1 76 | Height = 468 77 | HelpTag = "" 78 | Hierarchical = False 79 | Index = -2147483648 80 | InitialParent = "" 81 | InitialValue = "ID Name" 82 | Italic = False 83 | Left = 20 84 | LockBottom = False 85 | LockedInPosition= False 86 | LockLeft = True 87 | LockRight = False 88 | LockTop = True 89 | RequiresSelection= False 90 | Scope = 2 91 | ScrollbarHorizontal= False 92 | ScrollBarVertical= True 93 | SelectionType = 0 94 | TabIndex = 0 95 | TabPanelIndex = 0 96 | TabStop = True 97 | TextFont = "System" 98 | TextSize = 0.0 99 | TextUnit = 0 100 | Top = 20 101 | Underline = False 102 | UseFocusRing = True 103 | Visible = True 104 | Width = 298 105 | _ScrollOffset = 0 106 | _ScrollWidth = -1 107 | End 108 | Begin TextField fldFirstName 109 | AcceptTabs = False 110 | Alignment = 0 111 | AutoDeactivate = True 112 | AutomaticallyCheckSpelling= False 113 | BackColor = &cFFFFFF00 114 | Bold = False 115 | Border = True 116 | CueText = "First Name" 117 | DataField = "" 118 | DataSource = "" 119 | Enabled = True 120 | Format = "" 121 | Height = 22 122 | HelpTag = "" 123 | Index = -2147483648 124 | Italic = False 125 | Left = 397 126 | LimitText = 0 127 | LockBottom = False 128 | LockedInPosition= False 129 | LockLeft = True 130 | LockRight = False 131 | LockTop = True 132 | Mask = "" 133 | Password = False 134 | ReadOnly = False 135 | Scope = 2 136 | TabIndex = 1 137 | TabPanelIndex = 0 138 | TabStop = True 139 | Text = "" 140 | TextColor = &c00000000 141 | TextFont = "System" 142 | TextSize = 0.0 143 | TextUnit = 0 144 | Top = 278 145 | Underline = False 146 | UseFocusRing = True 147 | Visible = True 148 | Width = 162 149 | End 150 | Begin TextField fldLastName 151 | AcceptTabs = False 152 | Alignment = 0 153 | AutoDeactivate = True 154 | AutomaticallyCheckSpelling= False 155 | BackColor = &cFFFFFF00 156 | Bold = False 157 | Border = True 158 | CueText = "Last Name" 159 | DataField = "" 160 | DataSource = "" 161 | Enabled = True 162 | Format = "" 163 | Height = 22 164 | HelpTag = "" 165 | Index = -2147483648 166 | Italic = False 167 | Left = 571 168 | LimitText = 0 169 | LockBottom = False 170 | LockedInPosition= False 171 | LockLeft = True 172 | LockRight = False 173 | LockTop = True 174 | Mask = "" 175 | Password = False 176 | ReadOnly = False 177 | Scope = 2 178 | TabIndex = 2 179 | TabPanelIndex = 0 180 | TabStop = True 181 | Text = "" 182 | TextColor = &c00000000 183 | TextFont = "System" 184 | TextSize = 0.0 185 | TextUnit = 0 186 | Top = 278 187 | Underline = False 188 | UseFocusRing = True 189 | Visible = True 190 | Width = 162 191 | End 192 | Begin TextField fldCity 193 | AcceptTabs = False 194 | Alignment = 0 195 | AutoDeactivate = True 196 | AutomaticallyCheckSpelling= False 197 | BackColor = &cFFFFFF00 198 | Bold = False 199 | Border = True 200 | CueText = "City" 201 | DataField = "" 202 | DataSource = "" 203 | Enabled = True 204 | Format = "" 205 | Height = 22 206 | HelpTag = "" 207 | Index = -2147483648 208 | Italic = False 209 | Left = 397 210 | LimitText = 0 211 | LockBottom = False 212 | LockedInPosition= False 213 | LockLeft = True 214 | LockRight = False 215 | LockTop = True 216 | Mask = "" 217 | Password = False 218 | ReadOnly = False 219 | Scope = 2 220 | TabIndex = 3 221 | TabPanelIndex = 0 222 | TabStop = True 223 | Text = "" 224 | TextColor = &c00000000 225 | TextFont = "System" 226 | TextSize = 0.0 227 | TextUnit = 0 228 | Top = 312 229 | Underline = False 230 | UseFocusRing = True 231 | Visible = True 232 | Width = 162 233 | End 234 | Begin TextField fldState 235 | AcceptTabs = False 236 | Alignment = 0 237 | AutoDeactivate = True 238 | AutomaticallyCheckSpelling= False 239 | BackColor = &cFFFFFF00 240 | Bold = False 241 | Border = True 242 | CueText = "State" 243 | DataField = "" 244 | DataSource = "" 245 | Enabled = True 246 | Format = "" 247 | Height = 22 248 | HelpTag = "" 249 | Index = -2147483648 250 | Italic = False 251 | Left = 571 252 | LimitText = 0 253 | LockBottom = False 254 | LockedInPosition= False 255 | LockLeft = True 256 | LockRight = False 257 | LockTop = True 258 | Mask = "" 259 | Password = False 260 | ReadOnly = False 261 | Scope = 2 262 | TabIndex = 4 263 | TabPanelIndex = 0 264 | TabStop = True 265 | Text = "" 266 | TextColor = &c00000000 267 | TextFont = "System" 268 | TextSize = 0.0 269 | TextUnit = 0 270 | Top = 312 271 | Underline = False 272 | UseFocusRing = True 273 | Visible = True 274 | Width = 47 275 | End 276 | Begin TextField fldZip 277 | AcceptTabs = False 278 | Alignment = 0 279 | AutoDeactivate = True 280 | AutomaticallyCheckSpelling= False 281 | BackColor = &cFFFFFF00 282 | Bold = False 283 | Border = True 284 | CueText = "Zip" 285 | DataField = "" 286 | DataSource = "" 287 | Enabled = True 288 | Format = "" 289 | Height = 22 290 | HelpTag = "" 291 | Index = -2147483648 292 | Italic = False 293 | Left = 630 294 | LimitText = 0 295 | LockBottom = False 296 | LockedInPosition= False 297 | LockLeft = True 298 | LockRight = False 299 | LockTop = True 300 | Mask = "" 301 | Password = False 302 | ReadOnly = False 303 | Scope = 2 304 | TabIndex = 5 305 | TabPanelIndex = 0 306 | TabStop = True 307 | Text = "" 308 | TextColor = &c00000000 309 | TextFont = "System" 310 | TextSize = 0.0 311 | TextUnit = 0 312 | Top = 312 313 | Underline = False 314 | UseFocusRing = True 315 | Visible = True 316 | Width = 103 317 | End 318 | Begin TextField fldPhone 319 | AcceptTabs = False 320 | Alignment = 0 321 | AutoDeactivate = True 322 | AutomaticallyCheckSpelling= False 323 | BackColor = &cFFFFFF00 324 | Bold = False 325 | Border = True 326 | CueText = "Phone" 327 | DataField = "" 328 | DataSource = "" 329 | Enabled = True 330 | Format = "" 331 | Height = 22 332 | HelpTag = "" 333 | Index = -2147483648 334 | Italic = False 335 | Left = 397 336 | LimitText = 0 337 | LockBottom = False 338 | LockedInPosition= False 339 | LockLeft = True 340 | LockRight = False 341 | LockTop = True 342 | Mask = "" 343 | Password = False 344 | ReadOnly = False 345 | Scope = 2 346 | TabIndex = 6 347 | TabPanelIndex = 0 348 | TabStop = True 349 | Text = "" 350 | TextColor = &c00000000 351 | TextFont = "System" 352 | TextSize = 0.0 353 | TextUnit = 0 354 | Top = 346 355 | Underline = False 356 | UseFocusRing = True 357 | Visible = True 358 | Width = 162 359 | End 360 | Begin TextField fldEmail 361 | AcceptTabs = False 362 | Alignment = 0 363 | AutoDeactivate = True 364 | AutomaticallyCheckSpelling= False 365 | BackColor = &cFFFFFF00 366 | Bold = False 367 | Border = True 368 | CueText = "E-mail" 369 | DataField = "" 370 | DataSource = "" 371 | Enabled = True 372 | Format = "" 373 | Height = 22 374 | HelpTag = "" 375 | Index = -2147483648 376 | Italic = False 377 | Left = 571 378 | LimitText = 0 379 | LockBottom = False 380 | LockedInPosition= False 381 | LockLeft = True 382 | LockRight = False 383 | LockTop = True 384 | Mask = "" 385 | Password = False 386 | ReadOnly = False 387 | Scope = 2 388 | TabIndex = 7 389 | TabPanelIndex = 0 390 | TabStop = True 391 | Text = "" 392 | TextColor = &c00000000 393 | TextFont = "System" 394 | TextSize = 0.0 395 | TextUnit = 0 396 | Top = 346 397 | Underline = False 398 | UseFocusRing = True 399 | Visible = True 400 | Width = 162 401 | End 402 | Begin Canvas cvsPhoto 403 | AcceptFocus = False 404 | AcceptTabs = False 405 | AutoDeactivate = True 406 | Backdrop = 0 407 | DoubleBuffer = False 408 | Enabled = True 409 | EraseBackground = True 410 | Height = 192 411 | HelpTag = "" 412 | Index = -2147483648 413 | InitialParent = "" 414 | Left = 397 415 | LockBottom = False 416 | LockedInPosition= False 417 | LockLeft = True 418 | LockRight = False 419 | LockTop = True 420 | Scope = 2 421 | TabIndex = 8 422 | TabPanelIndex = 0 423 | TabStop = True 424 | Top = 20 425 | Transparent = True 426 | UseFocusRing = True 427 | Visible = True 428 | Width = 192 429 | End 430 | Begin CheckBox cbTaxable 431 | AutoDeactivate = True 432 | Bold = False 433 | Caption = "Taxable" 434 | DataField = "" 435 | DataSource = "" 436 | Enabled = True 437 | Height = 20 438 | HelpTag = "" 439 | Index = -2147483648 440 | InitialParent = "" 441 | Italic = False 442 | Left = 397 443 | LockBottom = False 444 | LockedInPosition= False 445 | LockLeft = True 446 | LockRight = False 447 | LockTop = True 448 | Scope = 2 449 | State = 0 450 | TabIndex = 9 451 | TabPanelIndex = 0 452 | TabStop = True 453 | TextFont = "System" 454 | TextSize = 0.0 455 | TextUnit = 0 456 | Top = 380 457 | Underline = False 458 | Value = False 459 | Visible = True 460 | Width = 100 461 | End 462 | Begin Timer tmrUpdateControls 463 | Enabled = True 464 | Index = -2147483648 465 | LockedInPosition= False 466 | Mode = 2 467 | Period = 250 468 | Scope = 2 469 | TabPanelIndex = 0 470 | End 471 | Begin Label lblRoundtrip 472 | AutoDeactivate = True 473 | Bold = False 474 | DataField = "" 475 | DataSource = "" 476 | Enabled = True 477 | Height = 20 478 | HelpTag = "" 479 | Index = -2147483648 480 | InitialParent = "" 481 | Italic = True 482 | Left = 561 483 | LockBottom = False 484 | LockedInPosition= False 485 | LockLeft = True 486 | LockRight = False 487 | LockTop = True 488 | Multiline = False 489 | Scope = 2 490 | Selectable = False 491 | TabIndex = 10 492 | TabPanelIndex = 0 493 | TabStop = True 494 | Text = "RoundTrip" 495 | TextAlign = 2 496 | TextColor = &c00000000 497 | TextFont = "SmallSystem" 498 | TextSize = 0.0 499 | TextUnit = 0 500 | Top = 468 501 | Transparent = True 502 | Underline = False 503 | Visible = True 504 | Width = 177 505 | End 506 | Begin CheckBox cbStore 507 | AutoDeactivate = True 508 | Bold = False 509 | Caption = "Store Customers" 510 | DataField = "" 511 | DataSource = "" 512 | Enabled = True 513 | Height = 20 514 | HelpTag = "" 515 | Index = -2147483648 516 | InitialParent = "" 517 | Italic = False 518 | Left = 601 519 | LockBottom = False 520 | LockedInPosition= False 521 | LockLeft = True 522 | LockRight = False 523 | LockTop = True 524 | Scope = 2 525 | State = 0 526 | TabIndex = 11 527 | TabPanelIndex = 0 528 | TabStop = True 529 | TextFont = "System" 530 | TextSize = 0.0 531 | TextUnit = 0 532 | Top = 20 533 | Underline = False 534 | Value = False 535 | Visible = True 536 | Width = 129 537 | End 538 | Begin M_REST.RESTMessageSurrogate_MTC smsgGetCustomerSurrogate 539 | Enabled = True 540 | Index = -2147483648 541 | IsBusy = False 542 | LockedInPosition= False 543 | Scope = 2 544 | TabPanelIndex = 0 545 | End 546 | Begin ProgressWheel pwBusy 547 | AutoDeactivate = True 548 | Enabled = True 549 | Height = 16 550 | HelpTag = "" 551 | Index = -2147483648 552 | InitialParent = "" 553 | Left = 344 554 | LockBottom = False 555 | LockedInPosition= False 556 | LockLeft = True 557 | LockRight = False 558 | LockTop = True 559 | Scope = 2 560 | TabIndex = 12 561 | TabPanelIndex = 0 562 | TabStop = True 563 | Top = 468 564 | Visible = True 565 | Width = 16 566 | End 567 | End 568 | #tag EndWindow 569 | 570 | #tag WindowCode 571 | #tag Event 572 | Sub Open() 573 | msgGetCustomerList.Send 574 | pwBusy.Visible = true 575 | End Sub 576 | #tag EndEvent 577 | 578 | 579 | #tag Method, Flags = &h21 580 | Private Sub ClearFields() 581 | fldFirstName.Text = "" 582 | fldLastName.Text = "" 583 | fldCity.Text = "" 584 | fldState.Text = "" 585 | fldZip.Text = "" 586 | fldEmail.Text = "" 587 | fldPhone.Text = "" 588 | 589 | cvsPhoto.Invalidate 590 | 591 | End Sub 592 | #tag EndMethod 593 | 594 | #tag Method, Flags = &h21 595 | Private Sub DisplayCustomer(cust As Eddies.Customer) 596 | if cust isa object then 597 | fldFirstName.Text = cust.FirstName 598 | fldLastName.Text = cust.LastName 599 | fldCity.Text = cust.City 600 | fldState.Text = cust.State 601 | fldZip.Text = cust.Zip 602 | fldPhone.Text = cust.Phone 603 | fldEmail.Text = cust.Email 604 | end if 605 | 606 | cvsPhoto.Invalidate 607 | 608 | End Sub 609 | #tag EndMethod 610 | 611 | #tag Method, Flags = &h21 612 | Private Sub RefreshListbox() 613 | lbCustomers.DeleteAllRows 614 | 615 | dim dict as Xojo.Core.Dictionary = msgGetCustomerList.ReturnGetAllCustomers 616 | if dict is nil then 617 | return 618 | end if 619 | 620 | for each entry as Xojo.Core.DictionaryEntry in dict 621 | dim id as text = entry.Key 622 | dim cust as Xojo.Core.Dictionary = entry.Value 623 | 624 | lbCustomers.AddRow id, cust.Value( "LastName" ) + ", " + cust.Value( "FirstName" ) 625 | lbCustomers.RowTag( lbCustomers.LastIndex ) = id 626 | next 627 | 628 | lbCustomers.SortedColumn = 0 629 | lbCustomers.Sort 630 | 631 | End Sub 632 | #tag EndMethod 633 | 634 | #tag Method, Flags = &h21 635 | Private Function RowOfCustomerID(id As Text) As Integer 636 | dim lastListIndex as integer = lbCustomers.ListCount - 1 637 | for row as integer = 0 to lastListIndex 638 | dim tag as variant = lbCustomers.RowTag( row ) 639 | if ( tag isa Eddies.Customer and Eddies.Customer( tag ).ID = id ) or _ 640 | (tag.Type = Variant.TypeText and tag.TextValue = id ) then 641 | return row 642 | end if 643 | next 644 | 645 | return -1 646 | 647 | End Function 648 | #tag EndMethod 649 | 650 | 651 | #tag ComputedProperty, Flags = &h21 652 | #tag Getter 653 | Get 654 | if cbStore.Value then 655 | // 656 | // Using a surrogate 657 | // 658 | if lbCustomers.ListIndex <> -1 and lbCustomers.RowTag( lbCustomers.ListIndex ) isa Eddies.Customer then 659 | return Eddies.Customer( lbCustomers.RowTag( lbCustomers.ListIndex ) ) 660 | else 661 | return nil 662 | end if 663 | 664 | else 665 | // 666 | // Using the direct method 667 | // 668 | if msgGetCustomer.IsConnected then 669 | return nil 670 | else 671 | return msgGetCustomer.ReturnGetCustomer 672 | end if 673 | end if 674 | 675 | End Get 676 | #tag EndGetter 677 | Private CurrentCustomer As Eddies.Customer 678 | #tag EndComputedProperty 679 | 680 | #tag Property, Flags = &h21 681 | Private PreviousListIndex As Integer = -1 682 | #tag EndProperty 683 | 684 | 685 | #tag EndWindowCode 686 | 687 | #tag Events msgGetCustomerList 688 | #tag Event 689 | Sub ResponseReceived(url As Text, httpStatus As Integer, payload As Auto) 690 | #pragma unused url 691 | #pragma unused httpStatus 692 | #pragma unused payload 693 | 694 | RefreshListbox 695 | 696 | lblRoundtrip.Text = format( me.RoundTripMs / 1000.0, "#,0.0" ) + " ms" 697 | pwBusy.Visible = msgGetCustomer.IsConnected or smsgGetCustomerSurrogate.IsBusy 698 | End Sub 699 | #tag EndEvent 700 | #tag EndEvents 701 | #tag Events msgGetCustomer 702 | #tag Event 703 | Sub ResponseReceived(url As Text, httpStatus As Integer, payload As Auto) 704 | #pragma unused url 705 | #pragma unused httpStatus 706 | #pragma unused payload 707 | 708 | // 709 | // If we were only using this one message, we could implment the code 710 | // below and be done with it. For this example project, though, since the 711 | // surrogate is there to show off handling of multiple, simultaneous 712 | // messages, we might as well use it for everything. 713 | // 714 | 715 | 'DisplayCustomer me.ReturnGetCustomer 716 | 'lblRoundtrip.Text = format( me.RoundTripMs / 1000.0, "#,0.0" ) + " s" 717 | 718 | End Sub 719 | #tag EndEvent 720 | #tag EndEvents 721 | #tag Events lbCustomers 722 | #tag Event 723 | Sub Change() 724 | if me.ListIndex <> PreviousListIndex then 725 | ClearFields 726 | 727 | if me.ListIndex <> -1 then 728 | dim tag as variant = me.RowTag( me.ListIndex ) 729 | dim id as text = if( tag isa Eddies.Customer, Eddies.Customer( tag ).ID, tag.TextValue ) 730 | 731 | // 732 | // Use surrogate method? 733 | // 734 | if cbStore.Value then 735 | // 736 | // See if we have the customer already 737 | // 738 | if tag isa Eddies.Customer then 739 | DisplayCustomer Eddies.Customer( tag ) 740 | else 741 | dim msg as new Eddies.GetCustomer 742 | msg.ID = id 743 | msg.Send smsgGetCustomerSurrogate 744 | end if 745 | 746 | else 747 | // 748 | // Use direct method 749 | // 750 | msgGetCustomer.Disconnect 751 | msgGetCustomer.ID = id 752 | msgGetCustomer.Send smsgGetCustomerSurrogate 753 | end if 754 | end if 755 | 756 | PreviousListIndex = me.ListIndex 757 | end if 758 | 759 | pwBusy.Visible = msgGetCustomer.IsConnected or smsgGetCustomerSurrogate.IsBusy 760 | End Sub 761 | #tag EndEvent 762 | #tag EndEvents 763 | #tag Events cvsPhoto 764 | #tag Event 765 | Sub Paint(g As Graphics, areas() As REALbasic.Rect) 766 | #pragma unused areas 767 | 768 | dim cust as Eddies.Customer = CurrentCustomer 769 | 770 | if cust isa object and cust.Photo isa object then 771 | g.DrawPicture cust.Photo, 0, 0 772 | 773 | else 774 | g.ClearRect 0, 0, g.Width, g.Height 775 | end if 776 | 777 | End Sub 778 | #tag EndEvent 779 | #tag EndEvents 780 | #tag Events tmrUpdateControls 781 | #tag Event 782 | Sub Action() 783 | dim value as boolean = not( msgGetCustomer.IsConnected or msgGetCustomerList.IsConnected ) 784 | 785 | if fldFirstName.Enabled = value then 786 | // 787 | // Nothing to do 788 | // 789 | return 790 | end if 791 | 792 | fldFirstName.Enabled = value 793 | fldLastName.Enabled = value 794 | fldCity.Enabled = value 795 | fldState.Enabled = value 796 | fldZip.Enabled = value 797 | fldPhone.Enabled = value 798 | fldEmail.Enabled = value 799 | cbTaxable.Enabled = value 800 | 801 | End Sub 802 | #tag EndEvent 803 | #tag EndEvents 804 | #tag Events cbStore 805 | #tag Event 806 | Sub Action() 807 | // 808 | // This checkbox will control whether the already-retrieved records 809 | // will be stored in the Listbox. If not, the existing records will be 810 | // cleared. 811 | // 812 | // This is a simple way to contrast the direct method of downloading information 813 | // by dragging a message to the window (msgGetCustomer) vs. using 814 | // the RESTMessageSurrogate_MTC class. 815 | // 816 | 817 | if not me.Value then 818 | // 819 | // Clear any existing records 820 | // 821 | dim lastListIndex as integer = lbCustomers.ListCount - 1 822 | for row as integer = 0 to lastListIndex 823 | dim tag as variant = lbCustomers.RowTag( row ) 824 | if tag isa Eddies.Customer then 825 | lbCustomers.RowTag( row ) = Eddies.Customer( tag ).ID 826 | end if 827 | next 828 | end if 829 | 830 | End Sub 831 | #tag EndEvent 832 | #tag EndEvents 833 | #tag Events smsgGetCustomerSurrogate 834 | #tag Event , Description = 546865205245535466756C20736572766572206861732072657475726E6564206120726573706F6E73652E 835 | Sub ResponseReceived(message As RESTMessage_MTC, url As Text, httpStatus As Integer, payload As Auto) 836 | #pragma unused url 837 | #pragma unused httpStatus 838 | #pragma unused payload 839 | 840 | // 841 | // Store the customer if the store checkbox is checked 842 | // 843 | 844 | dim response as Eddies.GetCustomer = Eddies.GetCustomer( message ) 845 | dim cust as Eddies.Customer = response.ReturnGetCustomer 846 | 847 | dim row as integer = RowOfCustomerID( cust.ID ) 848 | 849 | if cbStore.Value then 850 | lbCustomers.RowTag( row ) = cust 851 | end if 852 | 853 | if row = lbCustomers.ListIndex then 854 | DisplayCustomer cust 855 | end if 856 | 857 | lblRoundtrip.Text = format( response.RoundTripMs / 1000.0, "#,0.0" ) + " s" 858 | pwBusy.Visible = msgGetCustomer.IsConnected or smsgGetCustomerSurrogate.IsBusy 859 | End Sub 860 | #tag EndEvent 861 | #tag EndEvents 862 | #tag ViewBehavior 863 | #tag ViewProperty 864 | Name="BackColor" 865 | Visible=true 866 | Group="Background" 867 | InitialValue="&hFFFFFF" 868 | Type="Color" 869 | #tag EndViewProperty 870 | #tag ViewProperty 871 | Name="Backdrop" 872 | Visible=true 873 | Group="Background" 874 | Type="Picture" 875 | EditorType="Picture" 876 | #tag EndViewProperty 877 | #tag ViewProperty 878 | Name="CloseButton" 879 | Visible=true 880 | Group="Frame" 881 | InitialValue="True" 882 | Type="Boolean" 883 | EditorType="Boolean" 884 | #tag EndViewProperty 885 | #tag ViewProperty 886 | Name="Composite" 887 | Group="OS X (Carbon)" 888 | InitialValue="False" 889 | Type="Boolean" 890 | #tag EndViewProperty 891 | #tag ViewProperty 892 | Name="Frame" 893 | Visible=true 894 | Group="Frame" 895 | InitialValue="0" 896 | Type="Integer" 897 | EditorType="Enum" 898 | #tag EnumValues 899 | "0 - Document" 900 | "1 - Movable Modal" 901 | "2 - Modal Dialog" 902 | "3 - Floating Window" 903 | "4 - Plain Box" 904 | "5 - Shadowed Box" 905 | "6 - Rounded Window" 906 | "7 - Global Floating Window" 907 | "8 - Sheet Window" 908 | "9 - Metal Window" 909 | "11 - Modeless Dialog" 910 | #tag EndEnumValues 911 | #tag EndViewProperty 912 | #tag ViewProperty 913 | Name="FullScreen" 914 | Group="Behavior" 915 | InitialValue="False" 916 | Type="Boolean" 917 | EditorType="Boolean" 918 | #tag EndViewProperty 919 | #tag ViewProperty 920 | Name="FullScreenButton" 921 | Visible=true 922 | Group="Frame" 923 | InitialValue="False" 924 | Type="Boolean" 925 | EditorType="Boolean" 926 | #tag EndViewProperty 927 | #tag ViewProperty 928 | Name="HasBackColor" 929 | Visible=true 930 | Group="Background" 931 | InitialValue="False" 932 | Type="Boolean" 933 | #tag EndViewProperty 934 | #tag ViewProperty 935 | Name="Height" 936 | Visible=true 937 | Group="Size" 938 | InitialValue="400" 939 | Type="Integer" 940 | #tag EndViewProperty 941 | #tag ViewProperty 942 | Name="ImplicitInstance" 943 | Visible=true 944 | Group="Behavior" 945 | InitialValue="True" 946 | Type="Boolean" 947 | EditorType="Boolean" 948 | #tag EndViewProperty 949 | #tag ViewProperty 950 | Name="Interfaces" 951 | Visible=true 952 | Group="ID" 953 | Type="String" 954 | EditorType="String" 955 | #tag EndViewProperty 956 | #tag ViewProperty 957 | Name="LiveResize" 958 | Visible=true 959 | Group="Behavior" 960 | InitialValue="True" 961 | Type="Boolean" 962 | EditorType="Boolean" 963 | #tag EndViewProperty 964 | #tag ViewProperty 965 | Name="MacProcID" 966 | Group="OS X (Carbon)" 967 | InitialValue="0" 968 | Type="Integer" 969 | #tag EndViewProperty 970 | #tag ViewProperty 971 | Name="MaxHeight" 972 | Visible=true 973 | Group="Size" 974 | InitialValue="32000" 975 | Type="Integer" 976 | #tag EndViewProperty 977 | #tag ViewProperty 978 | Name="MaximizeButton" 979 | Visible=true 980 | Group="Frame" 981 | InitialValue="True" 982 | Type="Boolean" 983 | EditorType="Boolean" 984 | #tag EndViewProperty 985 | #tag ViewProperty 986 | Name="MaxWidth" 987 | Visible=true 988 | Group="Size" 989 | InitialValue="32000" 990 | Type="Integer" 991 | #tag EndViewProperty 992 | #tag ViewProperty 993 | Name="MenuBar" 994 | Visible=true 995 | Group="Menus" 996 | Type="MenuBar" 997 | EditorType="MenuBar" 998 | #tag EndViewProperty 999 | #tag ViewProperty 1000 | Name="MenuBarVisible" 1001 | Group="Behavior" 1002 | InitialValue="True" 1003 | Type="Boolean" 1004 | EditorType="Boolean" 1005 | #tag EndViewProperty 1006 | #tag ViewProperty 1007 | Name="MinHeight" 1008 | Visible=true 1009 | Group="Size" 1010 | InitialValue="64" 1011 | Type="Integer" 1012 | #tag EndViewProperty 1013 | #tag ViewProperty 1014 | Name="MinimizeButton" 1015 | Visible=true 1016 | Group="Frame" 1017 | InitialValue="True" 1018 | Type="Boolean" 1019 | EditorType="Boolean" 1020 | #tag EndViewProperty 1021 | #tag ViewProperty 1022 | Name="MinWidth" 1023 | Visible=true 1024 | Group="Size" 1025 | InitialValue="64" 1026 | Type="Integer" 1027 | #tag EndViewProperty 1028 | #tag ViewProperty 1029 | Name="Name" 1030 | Visible=true 1031 | Group="ID" 1032 | Type="String" 1033 | EditorType="String" 1034 | #tag EndViewProperty 1035 | #tag ViewProperty 1036 | Name="Placement" 1037 | Visible=true 1038 | Group="Behavior" 1039 | InitialValue="0" 1040 | Type="Integer" 1041 | EditorType="Enum" 1042 | #tag EnumValues 1043 | "0 - Default" 1044 | "1 - Parent Window" 1045 | "2 - Main Screen" 1046 | "3 - Parent Window Screen" 1047 | "4 - Stagger" 1048 | #tag EndEnumValues 1049 | #tag EndViewProperty 1050 | #tag ViewProperty 1051 | Name="Resizeable" 1052 | Visible=true 1053 | Group="Frame" 1054 | InitialValue="True" 1055 | Type="Boolean" 1056 | EditorType="Boolean" 1057 | #tag EndViewProperty 1058 | #tag ViewProperty 1059 | Name="Super" 1060 | Visible=true 1061 | Group="ID" 1062 | Type="String" 1063 | EditorType="String" 1064 | #tag EndViewProperty 1065 | #tag ViewProperty 1066 | Name="Title" 1067 | Visible=true 1068 | Group="Frame" 1069 | InitialValue="Untitled" 1070 | Type="String" 1071 | #tag EndViewProperty 1072 | #tag ViewProperty 1073 | Name="Visible" 1074 | Visible=true 1075 | Group="Behavior" 1076 | InitialValue="True" 1077 | Type="Boolean" 1078 | EditorType="Boolean" 1079 | #tag EndViewProperty 1080 | #tag ViewProperty 1081 | Name="Width" 1082 | Visible=true 1083 | Group="Size" 1084 | InitialValue="600" 1085 | Type="Integer" 1086 | #tag EndViewProperty 1087 | #tag EndViewBehavior 1088 | -------------------------------------------------------------------------------- /Harness Projects/Windows Folder/WndMain.xojo_window: -------------------------------------------------------------------------------- 1 | #tag Window 2 | Begin Window WndMain 3 | BackColor = &cFFFFFF00 4 | Backdrop = 0 5 | CloseButton = True 6 | Compatibility = "" 7 | Composite = False 8 | Frame = 0 9 | FullScreen = False 10 | FullScreenButton= False 11 | HasBackColor = False 12 | Height = 82 13 | ImplicitInstance= True 14 | LiveResize = True 15 | MacProcID = 0 16 | MaxHeight = 82 17 | MaximizeButton = False 18 | MaxWidth = 600 19 | MenuBar = 0 20 | MenuBarVisible = True 21 | MinHeight = 82 22 | MinimizeButton = True 23 | MinWidth = 600 24 | Placement = 0 25 | Resizeable = False 26 | Title = "Main" 27 | Visible = True 28 | Width = 600 29 | Begin Label Label1 30 | AutoDeactivate = True 31 | Bold = False 32 | DataField = "" 33 | DataSource = "" 34 | Enabled = True 35 | Height = 20 36 | HelpTag = "" 37 | Index = -2147483648 38 | InitialParent = "" 39 | Italic = False 40 | Left = 20 41 | LockBottom = False 42 | LockedInPosition= False 43 | LockLeft = True 44 | LockRight = False 45 | LockTop = True 46 | Multiline = True 47 | Scope = 0 48 | Selectable = False 49 | TabIndex = 0 50 | TabPanelIndex = 0 51 | Text = "Use the Examples menu above to choose an example." 52 | TextAlign = 1 53 | TextColor = &c00000000 54 | TextFont = "System" 55 | TextSize = 0.0 56 | TextUnit = 0 57 | Top = 20 58 | Transparent = True 59 | Underline = False 60 | Visible = True 61 | Width = 560 62 | End 63 | End 64 | #tag EndWindow 65 | 66 | #tag WindowCode 67 | #tag EndWindowCode 68 | 69 | #tag ViewBehavior 70 | #tag ViewProperty 71 | Name="BackColor" 72 | Visible=true 73 | Group="Background" 74 | InitialValue="&hFFFFFF" 75 | Type="Color" 76 | #tag EndViewProperty 77 | #tag ViewProperty 78 | Name="Backdrop" 79 | Visible=true 80 | Group="Background" 81 | Type="Picture" 82 | EditorType="Picture" 83 | #tag EndViewProperty 84 | #tag ViewProperty 85 | Name="CloseButton" 86 | Visible=true 87 | Group="Frame" 88 | InitialValue="True" 89 | Type="Boolean" 90 | EditorType="Boolean" 91 | #tag EndViewProperty 92 | #tag ViewProperty 93 | Name="Composite" 94 | Group="OS X (Carbon)" 95 | InitialValue="False" 96 | Type="Boolean" 97 | #tag EndViewProperty 98 | #tag ViewProperty 99 | Name="Frame" 100 | Visible=true 101 | Group="Frame" 102 | InitialValue="0" 103 | Type="Integer" 104 | EditorType="Enum" 105 | #tag EnumValues 106 | "0 - Document" 107 | "1 - Movable Modal" 108 | "2 - Modal Dialog" 109 | "3 - Floating Window" 110 | "4 - Plain Box" 111 | "5 - Shadowed Box" 112 | "6 - Rounded Window" 113 | "7 - Global Floating Window" 114 | "8 - Sheet Window" 115 | "9 - Metal Window" 116 | "11 - Modeless Dialog" 117 | #tag EndEnumValues 118 | #tag EndViewProperty 119 | #tag ViewProperty 120 | Name="FullScreen" 121 | Group="Behavior" 122 | InitialValue="False" 123 | Type="Boolean" 124 | EditorType="Boolean" 125 | #tag EndViewProperty 126 | #tag ViewProperty 127 | Name="FullScreenButton" 128 | Visible=true 129 | Group="Frame" 130 | InitialValue="False" 131 | Type="Boolean" 132 | EditorType="Boolean" 133 | #tag EndViewProperty 134 | #tag ViewProperty 135 | Name="HasBackColor" 136 | Visible=true 137 | Group="Background" 138 | InitialValue="False" 139 | Type="Boolean" 140 | #tag EndViewProperty 141 | #tag ViewProperty 142 | Name="Height" 143 | Visible=true 144 | Group="Size" 145 | InitialValue="400" 146 | Type="Integer" 147 | #tag EndViewProperty 148 | #tag ViewProperty 149 | Name="ImplicitInstance" 150 | Visible=true 151 | Group="Behavior" 152 | InitialValue="True" 153 | Type="Boolean" 154 | EditorType="Boolean" 155 | #tag EndViewProperty 156 | #tag ViewProperty 157 | Name="Interfaces" 158 | Visible=true 159 | Group="ID" 160 | Type="String" 161 | EditorType="String" 162 | #tag EndViewProperty 163 | #tag ViewProperty 164 | Name="LiveResize" 165 | Visible=true 166 | Group="Behavior" 167 | InitialValue="True" 168 | Type="Boolean" 169 | EditorType="Boolean" 170 | #tag EndViewProperty 171 | #tag ViewProperty 172 | Name="MacProcID" 173 | Group="OS X (Carbon)" 174 | InitialValue="0" 175 | Type="Integer" 176 | #tag EndViewProperty 177 | #tag ViewProperty 178 | Name="MaxHeight" 179 | Visible=true 180 | Group="Size" 181 | InitialValue="32000" 182 | Type="Integer" 183 | #tag EndViewProperty 184 | #tag ViewProperty 185 | Name="MaximizeButton" 186 | Visible=true 187 | Group="Frame" 188 | InitialValue="True" 189 | Type="Boolean" 190 | EditorType="Boolean" 191 | #tag EndViewProperty 192 | #tag ViewProperty 193 | Name="MaxWidth" 194 | Visible=true 195 | Group="Size" 196 | InitialValue="32000" 197 | Type="Integer" 198 | #tag EndViewProperty 199 | #tag ViewProperty 200 | Name="MenuBar" 201 | Visible=true 202 | Group="Menus" 203 | Type="MenuBar" 204 | EditorType="MenuBar" 205 | #tag EndViewProperty 206 | #tag ViewProperty 207 | Name="MenuBarVisible" 208 | Group="Behavior" 209 | InitialValue="True" 210 | Type="Boolean" 211 | EditorType="Boolean" 212 | #tag EndViewProperty 213 | #tag ViewProperty 214 | Name="MinHeight" 215 | Visible=true 216 | Group="Size" 217 | InitialValue="64" 218 | Type="Integer" 219 | #tag EndViewProperty 220 | #tag ViewProperty 221 | Name="MinimizeButton" 222 | Visible=true 223 | Group="Frame" 224 | InitialValue="True" 225 | Type="Boolean" 226 | EditorType="Boolean" 227 | #tag EndViewProperty 228 | #tag ViewProperty 229 | Name="MinWidth" 230 | Visible=true 231 | Group="Size" 232 | InitialValue="64" 233 | Type="Integer" 234 | #tag EndViewProperty 235 | #tag ViewProperty 236 | Name="Name" 237 | Visible=true 238 | Group="ID" 239 | Type="String" 240 | EditorType="String" 241 | #tag EndViewProperty 242 | #tag ViewProperty 243 | Name="Placement" 244 | Visible=true 245 | Group="Behavior" 246 | InitialValue="0" 247 | Type="Integer" 248 | EditorType="Enum" 249 | #tag EnumValues 250 | "0 - Default" 251 | "1 - Parent Window" 252 | "2 - Main Screen" 253 | "3 - Parent Window Screen" 254 | "4 - Stagger" 255 | #tag EndEnumValues 256 | #tag EndViewProperty 257 | #tag ViewProperty 258 | Name="Resizeable" 259 | Visible=true 260 | Group="Frame" 261 | InitialValue="True" 262 | Type="Boolean" 263 | EditorType="Boolean" 264 | #tag EndViewProperty 265 | #tag ViewProperty 266 | Name="Super" 267 | Visible=true 268 | Group="ID" 269 | Type="String" 270 | EditorType="String" 271 | #tag EndViewProperty 272 | #tag ViewProperty 273 | Name="Title" 274 | Visible=true 275 | Group="Frame" 276 | InitialValue="Untitled" 277 | Type="String" 278 | #tag EndViewProperty 279 | #tag ViewProperty 280 | Name="Visible" 281 | Visible=true 282 | Group="Behavior" 283 | InitialValue="True" 284 | Type="Boolean" 285 | EditorType="Boolean" 286 | #tag EndViewProperty 287 | #tag ViewProperty 288 | Name="Width" 289 | Visible=true 290 | Group="Size" 291 | InitialValue="600" 292 | Type="Integer" 293 | #tag EndViewProperty 294 | #tag EndViewBehavior 295 | -------------------------------------------------------------------------------- /Harness Projects/Windows Folder/WndSQLFormatter.xojo_window: -------------------------------------------------------------------------------- 1 | #tag Window 2 | Begin Window WndSQLFormatter 3 | BackColor = &cFFFFFF00 4 | Backdrop = 0 5 | CloseButton = True 6 | Compatibility = "" 7 | Composite = False 8 | Frame = 0 9 | FullScreen = False 10 | FullScreenButton= False 11 | HasBackColor = False 12 | Height = 400 13 | ImplicitInstance= True 14 | LiveResize = True 15 | MacProcID = 0 16 | MaxHeight = 32000 17 | MaximizeButton = True 18 | MaxWidth = 32000 19 | MenuBar = 0 20 | MenuBarVisible = True 21 | MinHeight = 64 22 | MinimizeButton = True 23 | MinWidth = 64 24 | Placement = 0 25 | Resizeable = True 26 | Title = "Untitled" 27 | Visible = True 28 | Width = 600 29 | Begin SQLFormatter msgSQLFormatter 30 | DBVendor = 1 31 | DefaultRESTType = "0" 32 | Enabled = True 33 | Index = -2147483648 34 | InputSQL = "" 35 | IsConnected = False 36 | LockedInPosition= False 37 | MessageSerialNumber= "" 38 | RESTType = "" 39 | RoundTripMs = 0.0 40 | RoundTripWithProcessingMs= 0.0 41 | Rspn_Formatted_SQL= "" 42 | Scope = 2 43 | TabPanelIndex = 0 44 | ValidateCertificates= False 45 | End 46 | Begin TextArea fldSQLIn 47 | AcceptTabs = False 48 | Alignment = 0 49 | AutoDeactivate = True 50 | AutomaticallyCheckSpelling= True 51 | BackColor = &cFFFFFF00 52 | Bold = False 53 | Border = True 54 | DataField = "" 55 | DataSource = "" 56 | Enabled = True 57 | Format = "" 58 | Height = 100 59 | HelpTag = "" 60 | HideSelection = True 61 | Index = -2147483648 62 | Italic = False 63 | Left = 20 64 | LimitText = 0 65 | LineHeight = 0.0 66 | LineSpacing = 1.0 67 | LockBottom = False 68 | LockedInPosition= False 69 | LockLeft = True 70 | LockRight = True 71 | LockTop = True 72 | Mask = "" 73 | Multiline = True 74 | ReadOnly = False 75 | Scope = 2 76 | ScrollbarHorizontal= False 77 | ScrollbarVertical= True 78 | Styled = True 79 | TabIndex = 0 80 | TabPanelIndex = 0 81 | TabStop = True 82 | Text = "select category, Count(*) AS ""Number of suppliers"" from suppliers where available_products > 45 group by category;" 83 | TextColor = &c00000000 84 | TextFont = "System" 85 | TextSize = 0.0 86 | TextUnit = 0 87 | Top = 20 88 | Underline = False 89 | UseFocusRing = True 90 | Visible = True 91 | Width = 560 92 | End 93 | Begin PushButton btnFormat 94 | AutoDeactivate = True 95 | Bold = False 96 | ButtonStyle = "0" 97 | Cancel = False 98 | Caption = "Format" 99 | Default = False 100 | Enabled = True 101 | Height = 20 102 | HelpTag = "" 103 | Index = -2147483648 104 | InitialParent = "" 105 | Italic = False 106 | Left = 448 107 | LockBottom = False 108 | LockedInPosition= False 109 | LockLeft = False 110 | LockRight = True 111 | LockTop = True 112 | Scope = 2 113 | TabIndex = 1 114 | TabPanelIndex = 0 115 | TabStop = True 116 | TextFont = "System" 117 | TextSize = 0.0 118 | TextUnit = 0 119 | Top = 132 120 | Underline = False 121 | Visible = True 122 | Width = 132 123 | End 124 | Begin TextArea fldSQLFormatted 125 | AcceptTabs = False 126 | Alignment = 0 127 | AutoDeactivate = True 128 | AutomaticallyCheckSpelling= True 129 | BackColor = &cFFFFFF00 130 | Bold = False 131 | Border = True 132 | DataField = "" 133 | DataSource = "" 134 | Enabled = True 135 | Format = "" 136 | Height = 216 137 | HelpTag = "" 138 | HideSelection = True 139 | Index = -2147483648 140 | Italic = False 141 | Left = 28 142 | LimitText = 0 143 | LineHeight = 0.0 144 | LineSpacing = 1.0 145 | LockBottom = True 146 | LockedInPosition= False 147 | LockLeft = True 148 | LockRight = True 149 | LockTop = True 150 | Mask = "" 151 | Multiline = True 152 | ReadOnly = False 153 | Scope = 2 154 | ScrollbarHorizontal= False 155 | ScrollbarVertical= True 156 | Styled = True 157 | TabIndex = 2 158 | TabPanelIndex = 0 159 | TabStop = True 160 | Text = "" 161 | TextColor = &c00000000 162 | TextFont = "System" 163 | TextSize = 0.0 164 | TextUnit = 0 165 | Top = 164 166 | Underline = False 167 | UseFocusRing = True 168 | Visible = True 169 | Width = 560 170 | End 171 | End 172 | #tag EndWindow 173 | 174 | #tag WindowCode 175 | #tag EndWindowCode 176 | 177 | #tag Events msgSQLFormatter 178 | #tag Event 179 | Sub ResponseReceived(url As Text, httpStatus As Integer, payload As Auto) 180 | #pragma unused url 181 | #pragma unused httpStatus 182 | #pragma unused payload 183 | 184 | fldSQLFormatted.Text = me.Rspn_Formatted_SQL 185 | return 186 | End Sub 187 | #tag EndEvent 188 | #tag EndEvents 189 | #tag Events btnFormat 190 | #tag Event 191 | Sub Action() 192 | msgSQLFormatter.InputSQL = fldSQLIn.Text.ToText 193 | msgSQLFormatter.Send 194 | 195 | End Sub 196 | #tag EndEvent 197 | #tag EndEvents 198 | #tag ViewBehavior 199 | #tag ViewProperty 200 | Name="BackColor" 201 | Visible=true 202 | Group="Background" 203 | InitialValue="&hFFFFFF" 204 | Type="Color" 205 | #tag EndViewProperty 206 | #tag ViewProperty 207 | Name="Backdrop" 208 | Visible=true 209 | Group="Background" 210 | Type="Picture" 211 | EditorType="Picture" 212 | #tag EndViewProperty 213 | #tag ViewProperty 214 | Name="CloseButton" 215 | Visible=true 216 | Group="Frame" 217 | InitialValue="True" 218 | Type="Boolean" 219 | EditorType="Boolean" 220 | #tag EndViewProperty 221 | #tag ViewProperty 222 | Name="Composite" 223 | Group="OS X (Carbon)" 224 | InitialValue="False" 225 | Type="Boolean" 226 | #tag EndViewProperty 227 | #tag ViewProperty 228 | Name="Frame" 229 | Visible=true 230 | Group="Frame" 231 | InitialValue="0" 232 | Type="Integer" 233 | EditorType="Enum" 234 | #tag EnumValues 235 | "0 - Document" 236 | "1 - Movable Modal" 237 | "2 - Modal Dialog" 238 | "3 - Floating Window" 239 | "4 - Plain Box" 240 | "5 - Shadowed Box" 241 | "6 - Rounded Window" 242 | "7 - Global Floating Window" 243 | "8 - Sheet Window" 244 | "9 - Metal Window" 245 | "11 - Modeless Dialog" 246 | #tag EndEnumValues 247 | #tag EndViewProperty 248 | #tag ViewProperty 249 | Name="FullScreen" 250 | Group="Behavior" 251 | InitialValue="False" 252 | Type="Boolean" 253 | EditorType="Boolean" 254 | #tag EndViewProperty 255 | #tag ViewProperty 256 | Name="FullScreenButton" 257 | Visible=true 258 | Group="Frame" 259 | InitialValue="False" 260 | Type="Boolean" 261 | EditorType="Boolean" 262 | #tag EndViewProperty 263 | #tag ViewProperty 264 | Name="HasBackColor" 265 | Visible=true 266 | Group="Background" 267 | InitialValue="False" 268 | Type="Boolean" 269 | #tag EndViewProperty 270 | #tag ViewProperty 271 | Name="Height" 272 | Visible=true 273 | Group="Size" 274 | InitialValue="400" 275 | Type="Integer" 276 | #tag EndViewProperty 277 | #tag ViewProperty 278 | Name="ImplicitInstance" 279 | Visible=true 280 | Group="Behavior" 281 | InitialValue="True" 282 | Type="Boolean" 283 | EditorType="Boolean" 284 | #tag EndViewProperty 285 | #tag ViewProperty 286 | Name="Interfaces" 287 | Visible=true 288 | Group="ID" 289 | Type="String" 290 | EditorType="String" 291 | #tag EndViewProperty 292 | #tag ViewProperty 293 | Name="LiveResize" 294 | Visible=true 295 | Group="Behavior" 296 | InitialValue="True" 297 | Type="Boolean" 298 | EditorType="Boolean" 299 | #tag EndViewProperty 300 | #tag ViewProperty 301 | Name="MacProcID" 302 | Group="OS X (Carbon)" 303 | InitialValue="0" 304 | Type="Integer" 305 | #tag EndViewProperty 306 | #tag ViewProperty 307 | Name="MaxHeight" 308 | Visible=true 309 | Group="Size" 310 | InitialValue="32000" 311 | Type="Integer" 312 | #tag EndViewProperty 313 | #tag ViewProperty 314 | Name="MaximizeButton" 315 | Visible=true 316 | Group="Frame" 317 | InitialValue="True" 318 | Type="Boolean" 319 | EditorType="Boolean" 320 | #tag EndViewProperty 321 | #tag ViewProperty 322 | Name="MaxWidth" 323 | Visible=true 324 | Group="Size" 325 | InitialValue="32000" 326 | Type="Integer" 327 | #tag EndViewProperty 328 | #tag ViewProperty 329 | Name="MenuBar" 330 | Visible=true 331 | Group="Menus" 332 | Type="MenuBar" 333 | EditorType="MenuBar" 334 | #tag EndViewProperty 335 | #tag ViewProperty 336 | Name="MenuBarVisible" 337 | Group="Behavior" 338 | InitialValue="True" 339 | Type="Boolean" 340 | EditorType="Boolean" 341 | #tag EndViewProperty 342 | #tag ViewProperty 343 | Name="MinHeight" 344 | Visible=true 345 | Group="Size" 346 | InitialValue="64" 347 | Type="Integer" 348 | #tag EndViewProperty 349 | #tag ViewProperty 350 | Name="MinimizeButton" 351 | Visible=true 352 | Group="Frame" 353 | InitialValue="True" 354 | Type="Boolean" 355 | EditorType="Boolean" 356 | #tag EndViewProperty 357 | #tag ViewProperty 358 | Name="MinWidth" 359 | Visible=true 360 | Group="Size" 361 | InitialValue="64" 362 | Type="Integer" 363 | #tag EndViewProperty 364 | #tag ViewProperty 365 | Name="Name" 366 | Visible=true 367 | Group="ID" 368 | Type="String" 369 | EditorType="String" 370 | #tag EndViewProperty 371 | #tag ViewProperty 372 | Name="Placement" 373 | Visible=true 374 | Group="Behavior" 375 | InitialValue="0" 376 | Type="Integer" 377 | EditorType="Enum" 378 | #tag EnumValues 379 | "0 - Default" 380 | "1 - Parent Window" 381 | "2 - Main Screen" 382 | "3 - Parent Window Screen" 383 | "4 - Stagger" 384 | #tag EndEnumValues 385 | #tag EndViewProperty 386 | #tag ViewProperty 387 | Name="Resizeable" 388 | Visible=true 389 | Group="Frame" 390 | InitialValue="True" 391 | Type="Boolean" 392 | EditorType="Boolean" 393 | #tag EndViewProperty 394 | #tag ViewProperty 395 | Name="Super" 396 | Visible=true 397 | Group="ID" 398 | Type="String" 399 | EditorType="String" 400 | #tag EndViewProperty 401 | #tag ViewProperty 402 | Name="Title" 403 | Visible=true 404 | Group="Frame" 405 | InitialValue="Untitled" 406 | Type="String" 407 | #tag EndViewProperty 408 | #tag ViewProperty 409 | Name="Visible" 410 | Visible=true 411 | Group="Behavior" 412 | InitialValue="True" 413 | Type="Boolean" 414 | EditorType="Boolean" 415 | #tag EndViewProperty 416 | #tag ViewProperty 417 | Name="Width" 418 | Visible=true 419 | Group="Size" 420 | InitialValue="600" 421 | Type="Integer" 422 | #tag EndViewProperty 423 | #tag EndViewBehavior 424 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Xojo REST Classes 2 | 3 | A REST client framework for Xojo. 4 | 5 | ## General Information 6 | 7 | There is no standard for RESTful servers. As such, creating classes that work with a variety can be tricky and time-consuming, and tend to make you to work directly with JSON or other raw data. This framework attempts to make the job a bit easier by allowing you to create "messages" by subclassing the main class and implementing various events. 8 | 9 | ### Installation 10 | 11 | Open the enclosed harness project and copy-and-paste the REST Resources folder into your own project. 12 | 13 | **Important**: _Do not drag the REST Resources folder directly from the folder into your project._ Xojo won't like it and will probably show all sorts of odd errors. 14 | 15 | ### Basic Use 16 | 17 | At its most basic, you need to create a "message" for each type of interaction with your RESTful server by subclassing `RESTMessage_MTC`. You might create one message that will login, another that will get a list of information, another to save some data. Each message must implement the `GetURLPattern` event (see below) and _should_ implement the `GetRESTType` event. 18 | 19 | If the REST server communicates with JSON, you can create properties in the message that correspond to the object keys. You can also use the `ExcludeFromOutgoingPayload` event to exclude a property or modify the key or value that will be included. In the `CancelSend` event you can cancel the send or change the URL, payload, or MIME type. 20 | 21 | If you expect information back from the server in the form of JSON, you can create properties with the prefix of "Return", e.g., _ReturnSuccess_, _ReturnFirstName_, etc., and the return payload will be parsed into those properties. You can adjust the prefix through the `Options` (see below). You can also use the `IncomingPayloadValueToProperty` event to "massage" a value or store it elsewhere. For example, if you expect an image to be returned as Base64-encoded, you can use that event to decode it, store the resulting image in a _ReturnImage_ property, then return `True` to prevent `RESTMessage_MTC` from processing the value further. 22 | 23 | `RESTMessage_MTC` will attempt to deserialize a JSON object into a class. For example, suppose you expect JSON from the server that looks like this: 24 | 25 | ```json 26 | { 27 | "user" : { 28 | "FirstName" : "John", 29 | "LastName" : "Doe", 30 | "Age" : 33 31 | } 32 | } 33 | ``` 34 | 35 | You can create a User class with properties _FirstName As Text_, _LastName As Text_, and _Age As Integer_, then create a property in the message _ReturnUser As User_. The class will automatically create an instance and fill in the properties for you. 36 | 37 | The `ResponseReceived` event will let you know when the server has responded and, if you choose, let you deal with the payload directly. 38 | 39 | There are times when it is not appropriate to have a single instance of a particular message. For example, if you need to save multiple records in a row. In those cases, you can create a `RESTMessageSurrogate_MTC` (see below) instead and send the message through it. The surrogate will raise all the events that the message would as if you had used `AddHandler` to map the message's events. 40 | 41 | ## Details 42 | 43 | This is a more detailed description of the `RESTMessage_MTC` class. 44 | 45 | ### Events 46 | 47 | | Event | Parameters | Return Value | Description | 48 | | ----- | ---------- | :----------: | ----------- | 49 | | CancelSend | ByRef url As Text,
ByRef httpAction As Text,
ByRef payload As Xojo.Core.MemoryBlock,
ByRef payloadMIMEType As Text | Boolean | The last chance to cancel sending the message, or change the URL, HTTP action, payload, or MIME type for the send. Set the payload to nil to avoid any payload. | 50 | | ContinueWaiting | | Boolean | The message has exceeded the time specified in _MessageOptions.TimeoutSeconds_. Return `True` to let it continue waiting for another period. (See _MessageOptions_ below.) | 51 | | Disconnected | | | The socket has disconnected. | 52 | | Error | msg As Text | | Some error has occurred during the connection. | 53 | | ExcludeFromOutgoingPayload | prop As Xojo.Introspection.PropertyInfo,
ByRef propName As Text,
ByRef propValue As Auto | Boolean | A message property is about to be included in the outgoing payload. If it shouldn't be, return `True`. You can also change the property name that will be used as the JSON object key or the value. | 54 | | GetRESTType | | RESTTypes | See The `GetRESTType` Event below. | 55 | | GetURLPattern | | Text | See The `GetURLPattern` Event below. | 56 | | IncomingPayloadValueToProperty | value As Auto,
prop As Xojo.Introspection.PropertyInfo,
hostObject As Object | Boolean | The incoming payload has a value that has been matched to a property of the message or one of the objects in its properties. Return `True` to prevent this value from being processed automatically, i.e., you will process it yourself. | 57 | | ObjectToJSON | o As Object,
typeInfo As Xojo.Introspection.TypeInfo | Auto | An object in one of the message's properties is about to be serialized, but you may prefer to do it yourself. If so, return a `Xojo.Core.Dictionary` or an `Auto()` array. If you do not implement this event or return nil, automatic processing will proceed. | 58 | | ResponseReceived | url As Text,
HTTPStatus As Integer,
payload As Auto | | The server has responded. The _url_ contains the server's URL, `HTTPStatus` the raw code returned by the server, and `payload` as the best form that RESTMesstage\_MTC could convert it into, i.e., `Xojo.Core.MemoryBlock`, `Auto()`, or `Xojo.Core.Dictionary`. | 59 | | Setup | | | The message object has been constructed. This is a good place to set the initial values of properties or _MessageOptions_. | 60 | | SkipIncomingPayloadProcessing | url As Text,
httpStatus As Integer,
ByRef payload As Auto | Boolean | The server has responded with a payload. If you prefer the class not try to automatically parse it, return `True`. | 61 | 62 | ### The `GetURLPattern` Event 63 | 64 | This event will let you specify the URL that will be used to connect to the server. It is raised each time you call `Send`. 65 | 66 | You must return some value here. 67 | 68 | The URL can be complete or may contain placeholders that represent properties within the message. For example, you need to get the weather in the zip code 99911 and the RESTful server requires the URL in the form: 69 | 70 | ``` 71 | http://www.someweathersite.com/api/get/zip/99911 72 | ``` 73 | 74 | You can create a property in your message subclass, _ZipCode_, and return the URL pattern like this: 75 | 76 | ``` 77 | http://www.someweathersite.com/api/get/zip/:ZipCode 78 | ``` 79 | 80 | `RESTMessage_MTC` will do the appropriate substitution. To send the message, you merely have to fill in the property and call `Send`. 81 | 82 | __Note__: Properties that are part of the URL pattern will never be included in the outgoing payload. 83 | 84 | ### The `GetRESTType` Event 85 | 86 | `RESTMessage_MTC` defines a _RESTTypes_ enum whose values either include or correspond to HTTP actions. Return the type appropriate for the message. As of v.1.0, these are: 87 | 88 | | Type | 89 | | --------- | 90 | | Unknown | 91 | | Create | 92 | | Read | 93 | | UpdateReplace | 94 | | UpdateModify | 95 | | Authenticate | 96 | | DELETE | 97 | | GET | 98 | | HEAD | 99 | | OPTIONS | 100 | | PATCH | 101 | | POST | 102 | | PUT | 103 | 104 | The uppercase types correspond directly to an HTTP action. The lowercase types are for convenience and will choose the proper action. For example, `Read` corresponds to the `GET` action. 105 | 106 | ### Properties 107 | 108 | | Property | Type | Read Only | Description | 109 | | -------- | ---- | :------: | ------------ | 110 | | DefaultRESTType | RESTTypes | no | The default REST type that will be used of the `GetRestType` event is not implemented. | 111 | | IsConnected | Boolean | __YES__ | Returns `True` if the socket is currently connected. | 112 | | MessageOptions | M\_REST.MessageOptions | no | Set the options for the message. See _MessageOptions_ below. | 113 | | MessageSerialNumber | Int64 | __YES__ | A unique number (within the session) assigned to each new instance of a message. | 114 | | MessageTag | Auto | no | Anything you wish to attach to a message. Does not get transmitted. | 115 | | RESTType | RESTTypes | __YES__ | The REST type that is ultimately used for the message. | 116 | | RoundTripMs | Double | __YES__ | The round-trip time, in milliseconds, from when the connection was initiated until a response received. | 117 | | RoundTripWithProcessingMs | Double | __YES__ | The round-trip time, in milliseconds, from when `Send` was invoked until response processing was finished. | 118 | 119 | ### Methods 120 | 121 | | Method | Parameters | Returns | Description | 122 | | ------ | ---------- | ------- | ----------- | 123 | | Disconnect | | | Disconnect from the server immediately. If not connected, will do nothing. | 124 | | Send | (opt) surrogate As RESTMessageSurrogate\_MTC | | Fill in the properties first, make sure the required events are implemented, then use this to send the message. __Note__: If the socket is already connected to the server, you will get an error. Check the _IsConnected_ property or just call `Disconnect` first.

If a surrogate is specified, incoming events will be raised for this message in it too (see below). | 125 | 126 | ### MessageOptions 127 | 128 | The _MessageOptions_ will let you set certain parameters for the message. For example, if a message is expected to take longer to send or receive or you want to make sure the payload is never sent. 129 | 130 | | Property | Type | Default | Description | 131 | | -------- | :--: | :-----: | ----------- | 132 | | AdjustDatesFromTimeZone | Boolean | False | When encoded dates are sent or received, this determines if the time zone should be honored. If so, the date will be adjusted according to the local time zone. | 133 | | ExpectedTextEncoding | Xojo.Core.TextEncoding | Xojo.Core.TextEncoding.UTF8 | When the payload is received, it is usually as UTF-8. If the server expects or delivers something different, specify that here. | 134 | | ReturnPropertyPrefix | Text | "Return" | Any property in your subclass that starts with this prefix will never be included in the outgoing payload and will be cleared and, if possible, populated by the incoming payload. These properties may be a basic type like String, Text, or Integer, a Dictionary, Auto() array, or an object whose public properties correspond to the incoming JSON object. | 135 | | SendWithPayloadIfAvailable | Boolean | True | For any HTTP action _other_ than GET, the class will attempt to construct and attach a payload using the properties of the message that (1) are not "Return" properties and (2) have not been included in the URL pattern. Set this to `True` to avoid that processing in all cases. | 136 | | TimeoutSeconds | Integer | 5 | Sets how long a message can wait before the `ContinueWaiting` event is raised. | 137 | 138 | ### RESTMessageSurrogate_MTC 139 | 140 | The `RESTMessageSurrogate_MTC` class will act as a stand-in for a message after it is sent. Drag the class to your window and implement its events. When sending a message, use the optional second parameter to specify the surrogate. 141 | 142 | __Note__: Events will be raised in the message first and then in the surrogate, except if an event returns a Boolean, returning `True` in the message will prevent the event from being raised in the surrogate. 143 | 144 | Generally it doesn't make much sense to implement the same event in both the message and a surrogate. The surrogate is there for situations where dragging a single copy of a message to your window does not make sense, e.g., you need to quickly save multiple records in a row. 145 | 146 | The parameters of each event match the parameters of the `RESTMessage_MTC` or `Xojo.Net.HTTPSocket` with the instance of the message as the first parameter in each case. This emulates using `AddHandler` to intercept the message's events. 147 | 148 | You can also use the _RESTMessage\_MTC.MessageTag_ property to further identify an instance of a message. 149 | 150 | The `RESTMessageSurrogate_MTC` has some additional properties and methods. 151 | 152 | #### Methods 153 | 154 | | Method | Parameters | Returns | Description | 155 | | ------ | ---------- | ------- | ----------- | 156 | | DisconnectAll | | | Disconnect all of the outstanding messages | 157 | | DisconnectMessage | msg As RESTMessage\_MTC | | Disconnect a single message | 158 | | OutstandingMessages | | RESTMessage\_MTC() | An array of outstanding messages | 159 | 160 | #### Properties 161 | 162 | | Property | Type | Default | Description | 163 | | -------- | :--: | :-----: | ----------- | 164 | | IsBusy | Boolean | | Returns `True` if there are still outstanding messages | 165 | 166 | ## Contributions 167 | 168 | Contributions to this project are welcome. Fork it to your own repo, then submit changes. However, be forewarned that only those changes that we deem universally useful will be included. 169 | 170 | ## Who Did This? 171 | 172 | This project was designed and implemented by: 173 | 174 | * Kem Tekinay (ktekinay at mactechnologies.com) 175 | 176 | With special thanks to [Advanced Medical Pricing Solutions, Inc.](http://www.advancedpricing.com) for making this possible. 177 | 178 | ## Release Notes 179 | 180 | 1.2 (May 18, 2016) 181 | 182 | - Added `RESTMessageSurrogate_MTC.Sent` event. 183 | - Changed where _ResponseReceivedMicroseconds_ is recorded. 184 | - Changed the parameter _sender_ to _message_ in `RESTMessageSurrogate_MTC` events. 185 | 186 | 1.1 (May 18, 2016) 187 | 188 | - Changed _Options_ property to _MessageOptions_ to prevent possible conflicts in subclasses. 189 | - Added _MessageSerialNumber_ property. 190 | - Added _RoundTripWithProcessingMs_ property. 191 | - Added _MessageTag_ property. 192 | - Added `RESTMessageSurrogate_MTC` class. 193 | 194 | 1.0 (May 12, 2016) 195 | 196 | - Initial release. 197 | -------------------------------------------------------------------------------- /REST Resources/M_REST.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Module 2 | Protected Module M_REST 3 | #tag Method, Flags = &h21 4 | Private Function GetZeroParamConstructor(ti As Xojo.Introspection.TypeInfo) As Xojo.Introspection.ConstructorInfo 5 | dim constructors() as Xojo.Introspection.ConstructorInfo = ti.Constructors 6 | 7 | // 8 | // Works backwords in the hope that that subclass Constructor if any, is later in the array 9 | // 10 | for i as integer = constructors.Ubound downto 0 11 | dim c as Xojo.Introspection.ConstructorInfo = constructors( i ) 12 | try 13 | #pragma BreakOnExceptions false 14 | dim params() as Xojo.Introspection.ParameterInfo = c.Parameters 15 | #pragma BreakOnExceptions default 16 | if params.Ubound = -1 then 17 | return c 18 | end if 19 | 20 | catch err as OutOfBoundsException 21 | // 22 | // A bug in Xojo as of 2016r11 when there is no 23 | // specific Constructor created for the class 24 | // If this exception is raised, we've found the only 25 | // Constructor 26 | return c 27 | 28 | end try 29 | next i 30 | 31 | return nil 32 | 33 | End Function 34 | #tag EndMethod 35 | 36 | 37 | #tag ViewBehavior 38 | #tag ViewProperty 39 | Name="Index" 40 | Visible=true 41 | Group="ID" 42 | InitialValue="-2147483648" 43 | Type="Integer" 44 | #tag EndViewProperty 45 | #tag ViewProperty 46 | Name="Left" 47 | Visible=true 48 | Group="Position" 49 | InitialValue="0" 50 | Type="Integer" 51 | #tag EndViewProperty 52 | #tag ViewProperty 53 | Name="Name" 54 | Visible=true 55 | Group="ID" 56 | Type="String" 57 | #tag EndViewProperty 58 | #tag ViewProperty 59 | Name="Super" 60 | Visible=true 61 | Group="ID" 62 | Type="String" 63 | #tag EndViewProperty 64 | #tag ViewProperty 65 | Name="Top" 66 | Visible=true 67 | Group="Position" 68 | InitialValue="0" 69 | Type="Integer" 70 | #tag EndViewProperty 71 | #tag EndViewBehavior 72 | End Module 73 | #tag EndModule 74 | -------------------------------------------------------------------------------- /REST Resources/M_REST/ClassMeta.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Private Class ClassMeta 3 | #tag Method, Flags = &h0 4 | Sub Constructor() 5 | ReturnPropertiesDict = new Xojo.Core.Dictionary 6 | SendPropertiesDict = new Xojo.Core.Dictionary 7 | End Sub 8 | #tag EndMethod 9 | 10 | 11 | #tag Property, Flags = &h0 12 | ReturnPropertiesDict As Xojo.Core.Dictionary 13 | #tag EndProperty 14 | 15 | #tag Property, Flags = &h0 16 | SendPropertiesDict As Xojo.Core.Dictionary 17 | #tag EndProperty 18 | 19 | 20 | #tag ViewBehavior 21 | #tag ViewProperty 22 | Name="Index" 23 | Visible=true 24 | Group="ID" 25 | InitialValue="-2147483648" 26 | Type="Integer" 27 | #tag EndViewProperty 28 | #tag ViewProperty 29 | Name="Left" 30 | Visible=true 31 | Group="Position" 32 | InitialValue="0" 33 | Type="Integer" 34 | #tag EndViewProperty 35 | #tag ViewProperty 36 | Name="Name" 37 | Visible=true 38 | Group="ID" 39 | Type="String" 40 | #tag EndViewProperty 41 | #tag ViewProperty 42 | Name="Super" 43 | Visible=true 44 | Group="ID" 45 | Type="String" 46 | #tag EndViewProperty 47 | #tag ViewProperty 48 | Name="Top" 49 | Visible=true 50 | Group="Position" 51 | InitialValue="0" 52 | Type="Integer" 53 | #tag EndViewProperty 54 | #tag EndViewBehavior 55 | End Class 56 | #tag EndClass 57 | -------------------------------------------------------------------------------- /REST Resources/M_REST/Options.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class Options 3 | Implements PrivateOptions 4 | #tag Method, Flags = &h0 5 | Sub Constructor() 6 | ExpectedTextEncoding = Xojo.Core.TextEncoding.UTF8 7 | End Sub 8 | #tag EndMethod 9 | 10 | #tag Method, Flags = &h21 11 | Private Sub SetParentMessage(msg As M_REST.RESTMessage_MTC) 12 | if msg <> ParentMessage then 13 | ParentMessage = msg 14 | PrivateMessage( msg ).ClearClassMeta 15 | end if 16 | 17 | End Sub 18 | #tag EndMethod 19 | 20 | 21 | #tag Property, Flags = &h0 22 | AdjustDatesForTimeZone As Boolean 23 | #tag EndProperty 24 | 25 | #tag ComputedProperty, Flags = &h0 26 | #tag Getter 27 | Get 28 | dim result as Xojo.Core.TextEncoding = mExpectedTextEncoding 29 | if result is nil then 30 | result = Xojo.Core.TextEncoding.UTF8 31 | end if 32 | 33 | return result 34 | End Get 35 | #tag EndGetter 36 | #tag Setter 37 | Set 38 | mExpectedTextEncoding = value 39 | End Set 40 | #tag EndSetter 41 | ExpectedTextEncoding As Xojo.Core.TextEncoding 42 | #tag EndComputedProperty 43 | 44 | #tag Property, Flags = &h21 45 | Private mExpectedTextEncoding As Xojo.Core.TextEncoding 46 | #tag EndProperty 47 | 48 | #tag Property, Flags = &h21 49 | Private mParentMessageWR As WeakRef 50 | #tag EndProperty 51 | 52 | #tag Property, Flags = &h21 53 | Attributes( hidden ) Private mReturnPropertyPrefix As Text = "Return" 54 | #tag EndProperty 55 | 56 | #tag ComputedProperty, Flags = &h21 57 | #tag Getter 58 | Get 59 | if mParentMessageWR is nil then 60 | return nil 61 | else 62 | return M_REST.RESTMessage_MTC( mParentMessageWR.Value ) 63 | end if 64 | 65 | End Get 66 | #tag EndGetter 67 | #tag Setter 68 | Set 69 | if value is nil then 70 | mParentMessageWR = nil 71 | else 72 | mParentMessageWR = new WeakRef( value ) 73 | end if 74 | 75 | End Set 76 | #tag EndSetter 77 | Private ParentMessage As M_REST.RESTMessage_MTC 78 | #tag EndComputedProperty 79 | 80 | #tag ComputedProperty, Flags = &h0 81 | #tag Getter 82 | Get 83 | return mReturnPropertyPrefix 84 | 85 | End Get 86 | #tag EndGetter 87 | #tag Setter 88 | Set 89 | value = value.Trim 90 | 91 | // 92 | // If the prefix has changed, the parent has to regenerate its 93 | // meta 94 | // 95 | 96 | if value <> mReturnPropertyPrefix then 97 | mReturnPropertyPrefix = value 98 | dim parent as RESTMessage_MTC = ParentMessage 99 | if parent isa object then 100 | PrivateMessage( parent ).ClearClassMeta 101 | end if 102 | end if 103 | 104 | End Set 105 | #tag EndSetter 106 | ReturnPropertyPrefix As Text 107 | #tag EndComputedProperty 108 | 109 | #tag Property, Flags = &h0 110 | SendWithPayloadIfAvailable As Boolean = True 111 | #tag EndProperty 112 | 113 | #tag Property, Flags = &h0 114 | TimeoutSeconds As Integer = 5 115 | #tag EndProperty 116 | 117 | 118 | #tag ViewBehavior 119 | #tag ViewProperty 120 | Name="AdjustDatesForTimeZone" 121 | Group="Behavior" 122 | Type="Boolean" 123 | #tag EndViewProperty 124 | #tag ViewProperty 125 | Name="Index" 126 | Visible=true 127 | Group="ID" 128 | InitialValue="-2147483648" 129 | Type="Integer" 130 | #tag EndViewProperty 131 | #tag ViewProperty 132 | Name="Left" 133 | Visible=true 134 | Group="Position" 135 | InitialValue="0" 136 | Type="Integer" 137 | #tag EndViewProperty 138 | #tag ViewProperty 139 | Name="Name" 140 | Visible=true 141 | Group="ID" 142 | Type="String" 143 | #tag EndViewProperty 144 | #tag ViewProperty 145 | Name="ReturnPropertyPrefix" 146 | Group="Behavior" 147 | Type="Text" 148 | #tag EndViewProperty 149 | #tag ViewProperty 150 | Name="SendWithPayloadIfAvailable" 151 | Group="Behavior" 152 | InitialValue="True" 153 | Type="Boolean" 154 | #tag EndViewProperty 155 | #tag ViewProperty 156 | Name="Super" 157 | Visible=true 158 | Group="ID" 159 | Type="String" 160 | #tag EndViewProperty 161 | #tag ViewProperty 162 | Name="TimeoutSeconds" 163 | Group="Behavior" 164 | InitialValue="5" 165 | Type="Integer" 166 | #tag EndViewProperty 167 | #tag ViewProperty 168 | Name="Top" 169 | Visible=true 170 | Group="Position" 171 | InitialValue="0" 172 | Type="Integer" 173 | #tag EndViewProperty 174 | #tag EndViewBehavior 175 | End Class 176 | #tag EndClass 177 | -------------------------------------------------------------------------------- /REST Resources/M_REST/PrivateMessage.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface 2 | Private Interface PrivateMessage 3 | #tag Method, Flags = &h0 4 | Sub ClearClassMeta() 5 | 6 | End Sub 7 | #tag EndMethod 8 | 9 | 10 | #tag ViewBehavior 11 | #tag ViewProperty 12 | Name="Index" 13 | Visible=true 14 | Group="ID" 15 | InitialValue="-2147483648" 16 | Type="Integer" 17 | #tag EndViewProperty 18 | #tag ViewProperty 19 | Name="Left" 20 | Visible=true 21 | Group="Position" 22 | InitialValue="0" 23 | Type="Integer" 24 | #tag EndViewProperty 25 | #tag ViewProperty 26 | Name="Name" 27 | Visible=true 28 | Group="ID" 29 | Type="String" 30 | #tag EndViewProperty 31 | #tag ViewProperty 32 | Name="Super" 33 | Visible=true 34 | Group="ID" 35 | Type="String" 36 | #tag EndViewProperty 37 | #tag ViewProperty 38 | Name="Top" 39 | Visible=true 40 | Group="Position" 41 | InitialValue="0" 42 | Type="Integer" 43 | #tag EndViewProperty 44 | #tag EndViewBehavior 45 | End Interface 46 | #tag EndInterface 47 | -------------------------------------------------------------------------------- /REST Resources/M_REST/PrivateOptions.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface 2 | Private Interface PrivateOptions 3 | #tag Method, Flags = &h0 4 | Sub SetParentMessage(msg As M_REST.RESTMessage_MTC) 5 | 6 | End Sub 7 | #tag EndMethod 8 | 9 | 10 | #tag ViewBehavior 11 | #tag ViewProperty 12 | Name="Index" 13 | Visible=true 14 | Group="ID" 15 | InitialValue="-2147483648" 16 | Type="Integer" 17 | #tag EndViewProperty 18 | #tag ViewProperty 19 | Name="Left" 20 | Visible=true 21 | Group="Position" 22 | InitialValue="0" 23 | Type="Integer" 24 | #tag EndViewProperty 25 | #tag ViewProperty 26 | Name="Name" 27 | Visible=true 28 | Group="ID" 29 | Type="String" 30 | #tag EndViewProperty 31 | #tag ViewProperty 32 | Name="Super" 33 | Visible=true 34 | Group="ID" 35 | Type="String" 36 | #tag EndViewProperty 37 | #tag ViewProperty 38 | Name="Top" 39 | Visible=true 40 | Group="Position" 41 | InitialValue="0" 42 | Type="Integer" 43 | #tag EndViewProperty 44 | #tag EndViewBehavior 45 | End Interface 46 | #tag EndInterface 47 | -------------------------------------------------------------------------------- /REST Resources/M_REST/PrivateSurrogate.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface 2 | Private Interface PrivateSurrogate 3 | #tag Method, Flags = &h0 4 | Sub AppendMessage(msg As M_REST.RESTMessage_MTC) 5 | 6 | End Sub 7 | #tag EndMethod 8 | 9 | #tag Method, Flags = &h0 10 | Function RaiseAuthenticationRequired(message As RESTMessage_MTC, realm As Text, ByRef name As Text, ByRef password As Text) As Boolean 11 | 12 | End Function 13 | #tag EndMethod 14 | 15 | #tag Method, Flags = &h0 16 | Function RaiseContinueWaiting(message As RESTMessage_MTC) As Boolean 17 | 18 | End Function 19 | #tag EndMethod 20 | 21 | #tag Method, Flags = &h0 22 | Sub RaiseDisconnected(message As RESTMessage_MTC) 23 | 24 | End Sub 25 | #tag EndMethod 26 | 27 | #tag Method, Flags = &h0 28 | Sub RaiseError(message As RESTMessage_MTC, msg As Text) 29 | 30 | End Sub 31 | #tag EndMethod 32 | 33 | #tag Method, Flags = &h0 34 | Sub RaiseHeadersReceived(message As RESTMessage_MTC, url As Text, httpStatus As Integer) 35 | 36 | End Sub 37 | #tag EndMethod 38 | 39 | #tag Method, Flags = &h0 40 | Sub RaiseReceiveProgress(message As RESTMessage_MTC, bytesReceived As Int64, totalBytes As Int64, newData As Xojo.Core.MemoryBlock) 41 | 42 | End Sub 43 | #tag EndMethod 44 | 45 | #tag Method, Flags = &h0 46 | Sub RaiseResponseReceived(message As RESTMessage_MTC, url As Text, httpStatus As Integer, payload As Auto) 47 | 48 | End Sub 49 | #tag EndMethod 50 | 51 | #tag Method, Flags = &h0 52 | Sub RaiseSendProgress(message As RESTMessage_MTC, bytesSent As Int64, bytesLeft As Int64) 53 | 54 | End Sub 55 | #tag EndMethod 56 | 57 | #tag Method, Flags = &h0 58 | Sub RaiseSent(message As RESTMessage_MTC) 59 | 60 | End Sub 61 | #tag EndMethod 62 | 63 | #tag Method, Flags = &h0 64 | Sub RemoveMessage(msg As M_REST.RESTMessage_MTC) 65 | 66 | End Sub 67 | #tag EndMethod 68 | 69 | 70 | End Interface 71 | #tag EndInterface 72 | -------------------------------------------------------------------------------- /REST Resources/M_REST/RESTException.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class RESTException 3 | Inherits RuntimeException 4 | #tag Method, Flags = &h0 5 | Sub Constructor() 6 | 7 | End Sub 8 | #tag EndMethod 9 | 10 | #tag Method, Flags = &h0 11 | Sub Constructor(reason As Text) 12 | self.Reason = reason 13 | End Sub 14 | #tag EndMethod 15 | 16 | 17 | #tag ViewBehavior 18 | #tag ViewProperty 19 | Name="ErrorNumber" 20 | Group="Behavior" 21 | InitialValue="0" 22 | Type="Integer" 23 | #tag EndViewProperty 24 | #tag ViewProperty 25 | Name="Index" 26 | Visible=true 27 | Group="ID" 28 | InitialValue="-2147483648" 29 | Type="Integer" 30 | #tag EndViewProperty 31 | #tag ViewProperty 32 | Name="Left" 33 | Visible=true 34 | Group="Position" 35 | InitialValue="0" 36 | Type="Integer" 37 | #tag EndViewProperty 38 | #tag ViewProperty 39 | Name="Message" 40 | Group="Behavior" 41 | Type="String" 42 | EditorType="MultiLineEditor" 43 | #tag EndViewProperty 44 | #tag ViewProperty 45 | Name="Name" 46 | Visible=true 47 | Group="ID" 48 | Type="String" 49 | #tag EndViewProperty 50 | #tag ViewProperty 51 | Name="Reason" 52 | Group="Behavior" 53 | Type="Text" 54 | #tag EndViewProperty 55 | #tag ViewProperty 56 | Name="Super" 57 | Visible=true 58 | Group="ID" 59 | Type="String" 60 | #tag EndViewProperty 61 | #tag ViewProperty 62 | Name="Top" 63 | Visible=true 64 | Group="Position" 65 | InitialValue="0" 66 | Type="Integer" 67 | #tag EndViewProperty 68 | #tag EndViewBehavior 69 | End Class 70 | #tag EndClass 71 | -------------------------------------------------------------------------------- /REST Resources/M_REST/RESTMessageSurrogate_MTC.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Class RESTMessageSurrogate_MTC 3 | Implements PrivateSurrogate 4 | #tag Method, Flags = &h21 5 | Private Sub AppendMessage(msg As M_REST.RESTMessage_MTC) 6 | OutstandingMessagesDict.Value( msg ) = nil 7 | 8 | End Sub 9 | #tag EndMethod 10 | 11 | #tag Method, Flags = &h0 12 | Sub DisconnectAll() 13 | for each entry as Xojo.Core.DictionaryEntry in OutstandingMessagesDict 14 | dim msg as M_REST.RESTMessage_MTC = M_REST.RESTMessage_MTC( entry.Key ) 15 | msg.Disconnect 16 | next 17 | 18 | OutstandingMessagesDict.RemoveAll 19 | 20 | End Sub 21 | #tag EndMethod 22 | 23 | #tag Method, Flags = &h0 24 | Sub DisconnectMessage(msg As M_REST.RESTMessage_MTC) 25 | msg.Disconnect 26 | 27 | End Sub 28 | #tag EndMethod 29 | 30 | #tag Method, Flags = &h0 31 | Function OutstandingMessages() As M_REST.RESTMessage_MTC() 32 | dim msgs() as M_REST.RESTMessage_MTC 33 | for each entry as Xojo.Core.DictionaryEntry in OutstandingMessagesDict 34 | msgs.Append M_REST.RESTMessage_MTC( entry.Key ) 35 | next 36 | 37 | return msgs 38 | 39 | End Function 40 | #tag EndMethod 41 | 42 | #tag Method, Flags = &h21 43 | Private Function RaiseAuthenticationRequired(message As RESTMessage_MTC, realm As Text, ByRef name As Text, ByRef password As Text) As Boolean 44 | return RaiseEvent AuthenticationRequired( message, realm, name, password ) 45 | End Function 46 | #tag EndMethod 47 | 48 | #tag Method, Flags = &h21 49 | Private Function RaiseContinueWaiting(message As RESTMessage_MTC) As Boolean 50 | return RaiseEvent ContinueWaiting( message ) 51 | End Function 52 | #tag EndMethod 53 | 54 | #tag Method, Flags = &h21 55 | Private Sub RaiseDisconnected(message As RESTMessage_MTC) 56 | RaiseEvent Disconnected( message ) 57 | End Sub 58 | #tag EndMethod 59 | 60 | #tag Method, Flags = &h21 61 | Private Sub RaiseError(message As RESTMessage_MTC, msg As Text) 62 | RaiseEvent Error( message, msg ) 63 | End Sub 64 | #tag EndMethod 65 | 66 | #tag Method, Flags = &h21 67 | Private Sub RaiseHeadersReceived(message As RESTMessage_MTC, url As Text, httpStatus As Integer) 68 | RaiseEvent HeadersReceived( message, url, httpStatus ) 69 | End Sub 70 | #tag EndMethod 71 | 72 | #tag Method, Flags = &h21 73 | Private Sub RaiseReceiveProgress(message As RESTMessage_MTC, bytesReceived As Int64, totalBytes As Int64, newData As Xojo.Core.MemoryBlock) 74 | RaiseEvent ReceiveProgress( message, bytesReceived, totalBytes, newData ) 75 | 76 | End Sub 77 | #tag EndMethod 78 | 79 | #tag Method, Flags = &h21 80 | Private Sub RaiseResponseReceived(message As RESTMessage_MTC, url As Text, httpStatus As Integer, payload As Auto) 81 | RaiseEvent ResponseReceived( message, url, httpStatus, payload ) 82 | End Sub 83 | #tag EndMethod 84 | 85 | #tag Method, Flags = &h21 86 | Private Sub RaiseSendProgress(message As RESTMessage_MTC, bytesSent As Int64, bytesLeft As Int64) 87 | RaiseEvent SendProgress( message, bytesSent, bytesLeft ) 88 | 89 | End Sub 90 | #tag EndMethod 91 | 92 | #tag Method, Flags = &h21, Description = 546865206D65737361676520686173206265656E2073656E742E 93 | Private Sub RaiseSent(message As RESTMessage_MTC) 94 | RaiseEvent Sent( message ) 95 | End Sub 96 | #tag EndMethod 97 | 98 | #tag Method, Flags = &h21 99 | Private Sub RemoveMessage(msg As M_REST.RESTMessage_MTC) 100 | #pragma BreakOnExceptions false 101 | try 102 | OutstandingMessagesDict.Remove msg 103 | catch err as KeyNotFoundException 104 | // 105 | // Already gone, so move on 106 | // 107 | end try 108 | #pragma BreakOnExceptions default 109 | 110 | End Sub 111 | #tag EndMethod 112 | 113 | 114 | #tag Hook, Flags = &h0, Description = 546865206D6573736167652072657175697265732061757468656E7469636174696F6E2E2053657420746865206E616D6520616E642070617373776F72642C207468656E2072657475726E20547275652E 115 | Event AuthenticationRequired(message As RESTMessage_MTC, realm As Text, ByRef name As Text, ByRef password As Text) As Boolean 116 | #tag EndHook 117 | 118 | #tag Hook, Flags = &h0, Description = 546865206D6573736167652068617320657863656564207468652074696D652073657420696E204F7074696F6E732E54696D656F75745365636F6E64732E2052657475726E205472756520746F20616C6C6F7720746865206D65737361676520746F206B6565702077616974696E672E 119 | Event ContinueWaiting(message As RESTMessage_MTC) As Boolean 120 | #tag EndHook 121 | 122 | #tag Hook, Flags = &h0, Description = 54686520736F636B65742068617320646973636F6E6E65637465642E 123 | Event Disconnected(message As RESTMessage_MTC) 124 | #tag EndHook 125 | 126 | #tag Hook, Flags = &h0, Description = 416E206572726F7220686173206F636375727265642E 127 | Event Error(message As RESTMessage_MTC, msg As Text) 128 | #tag EndHook 129 | 130 | #tag Hook, Flags = &h0, Description = 54686520686561646572732063616D65206261636B2066726F6D20746865207365727665722E 131 | Event HeadersReceived(message As RESTMessage_MTC, url As Text, httpStatus As Integer) 132 | #tag EndHook 133 | 134 | #tag Hook, Flags = &h0, Description = 546865207374617473206173206120726573706F6E73652069732072656365697665642E 135 | Event ReceiveProgress(message As RESTMessage_MTC, bytesReceived As Int64, totalBytes As Int64, newData As Xojo.Core.MemoryBlock) 136 | #tag EndHook 137 | 138 | #tag Hook, Flags = &h0, Description = 546865205245535466756C20736572766572206861732072657475726E6564206120726573706F6E73652E 139 | Event ResponseReceived(message As RESTMessage_MTC, url As Text, httpStatus As Integer, payload As Auto) 140 | #tag EndHook 141 | 142 | #tag Hook, Flags = &h0, Description = 546865207374617473206F662061206D657373616765206265696E672073656E742E 143 | Event SendProgress(message As RESTMessage_MTC, bytesSent As Int64, bytesLeft As Int64) 144 | #tag EndHook 145 | 146 | #tag Hook, Flags = &h0, Description = 546865206D65737361676520686173206265656E2073656E742E 147 | Event Sent(message As RESTMessage_MTC) 148 | #tag EndHook 149 | 150 | 151 | #tag ComputedProperty, Flags = &h0 152 | #tag Getter 153 | Get 154 | return OutstandingMessagesDict.Count <> 0 155 | End Get 156 | #tag EndGetter 157 | IsBusy As Boolean 158 | #tag EndComputedProperty 159 | 160 | #tag Property, Flags = &h21 161 | Attributes( hidden ) Private mOutstandingMessagesDict As Xojo.Core.Dictionary 162 | #tag EndProperty 163 | 164 | #tag ComputedProperty, Flags = &h21 165 | #tag Getter 166 | Get 167 | if mOutstandingMessagesDict is nil then 168 | mOutstandingMessagesDict = new Xojo.Core.Dictionary 169 | end if 170 | 171 | return mOutstandingMessagesDict 172 | End Get 173 | #tag EndGetter 174 | Private OutstandingMessagesDict As Xojo.Core.Dictionary 175 | #tag EndComputedProperty 176 | 177 | 178 | #tag ViewBehavior 179 | #tag ViewProperty 180 | Name="Index" 181 | Visible=true 182 | Group="ID" 183 | InitialValue="-2147483648" 184 | Type="Integer" 185 | #tag EndViewProperty 186 | #tag ViewProperty 187 | Name="IsBusy" 188 | Group="Behavior" 189 | Type="Boolean" 190 | #tag EndViewProperty 191 | #tag ViewProperty 192 | Name="Left" 193 | Visible=true 194 | Group="Position" 195 | InitialValue="0" 196 | Type="Integer" 197 | #tag EndViewProperty 198 | #tag ViewProperty 199 | Name="Name" 200 | Visible=true 201 | Group="ID" 202 | Type="String" 203 | #tag EndViewProperty 204 | #tag ViewProperty 205 | Name="Super" 206 | Visible=true 207 | Group="ID" 208 | Type="String" 209 | #tag EndViewProperty 210 | #tag ViewProperty 211 | Name="Top" 212 | Visible=true 213 | Group="Position" 214 | InitialValue="0" 215 | Type="Integer" 216 | #tag EndViewProperty 217 | #tag EndViewBehavior 218 | End Class 219 | #tag EndClass 220 | -------------------------------------------------------------------------------- /REST Resources/M_REST/RESTMessage_MTC.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Class RESTMessage_MTC 3 | Inherits Xojo.Net.HTTPSocket 4 | Implements PrivateMessage 5 | #tag Event 6 | Function AuthenticationRequired(Realm as Text, ByRef Name as Text, ByRef Password as Text) As Boolean 7 | dim surrogate as M_REST.PrivateSurrogate = MessageSurrogate 8 | 9 | if RaiseEvent AuthenticationRequired( realm, name, password ) or _ 10 | ( surrogate isa object and surrogate.RaiseAuthenticationRequired( self, realm, name, password ) ) then 11 | return true 12 | else 13 | return false 14 | end if 15 | 16 | End Function 17 | #tag EndEvent 18 | 19 | #tag Event 20 | Sub Error(err as RuntimeException) 21 | mIsConnected = false 22 | 23 | dim surrogate as M_REST.PrivateSurrogate = MessageSurrogate 24 | 25 | if surrogate isa object then 26 | surrogate.RemoveMessage self 27 | end if 28 | 29 | if err isa Xojo.Net.NetException then 30 | select case err.ErrorNumber 31 | case 102 32 | RaiseEvent Disconnected 33 | 34 | if surrogate isa object then 35 | surrogate.RaiseDisconnected( self ) 36 | end if 37 | 38 | case else 39 | RaiseEvent Error( err.Reason ) 40 | 41 | if surrogate isa object then 42 | surrogate.RaiseError( self, err.Reason ) 43 | end if 44 | 45 | end select 46 | 47 | MessageSurrogate = nil 48 | 49 | else 50 | 51 | MessageSurrogate = nil 52 | raise err 53 | 54 | end if 55 | 56 | 57 | End Sub 58 | #tag EndEvent 59 | 60 | #tag Event 61 | Sub FileReceived(URL as Text, HTTPStatus as Integer, File as xojo.IO.FolderItem) 62 | #pragma unused url 63 | #pragma unused httpStatus 64 | #pragma unused file 65 | 66 | // Do nothing for now 67 | End Sub 68 | #tag EndEvent 69 | 70 | #tag Event 71 | Sub HeadersReceived(URL as Text, HTTPStatus as Integer) 72 | RaiseEvent HeadersReceived( url, httpStatus ) 73 | 74 | dim surrogate as M_REST.PrivateSurrogate = MessageSurrogate 75 | if surrogate isa object then 76 | surrogate.RaiseHeadersReceived( self, url, httpStatus ) 77 | end if 78 | 79 | End Sub 80 | #tag EndEvent 81 | 82 | #tag Event 83 | Sub PageReceived(URL as Text, HTTPStatus as Integer, Content as xojo.Core.MemoryBlock) 84 | ResponseReceivedMicroseconds = Microseconds 85 | 86 | mIsConnected = false 87 | dim surrogate as M_REST.PrivateSurrogate = MessageSurrogate 88 | 89 | if surrogate isa object then 90 | surrogate.RemoveMessage self 91 | end if 92 | 93 | ClearReturnProperties 94 | 95 | dim payload as Auto = content 96 | 97 | if not SkipIncomingPayloadProcessing( url, httpStatus, payload ) then 98 | payload = ProcessPayload( payload ) 99 | end if 100 | 101 | ReceiveFinishedMicroseconds = microseconds 102 | RaiseEvent ResponseReceived url, httpStatus, payload 103 | 104 | // 105 | // NOTE: If the caller no longer exists, you will get a NilObjectException here 106 | // 107 | 108 | if surrogate isa object then 109 | surrogate.RaiseResponseReceived( self, url, httpStatus, payload ) 110 | MessageSurrogate = nil 111 | end if 112 | 113 | End Sub 114 | #tag EndEvent 115 | 116 | #tag Event 117 | Sub ReceiveProgress(BytesReceived as Int64, TotalBytes as Int64, NewData as xojo.Core.MemoryBlock) 118 | RaiseEvent ReceiveProgress( bytesReceived, totalBytes, newData ) 119 | 120 | dim surrogate as M_REST.PrivateSurrogate = MessageSurrogate 121 | if surrogate isa object then 122 | surrogate.RaiseReceiveProgress( self, bytesReceived, totalBytes, newData ) 123 | end if 124 | 125 | End Sub 126 | #tag EndEvent 127 | 128 | #tag Event 129 | Sub SendProgress(BytesSent as Int64, BytesLeft as Int64) 130 | RaiseEvent SendProgress( bytesSent, bytesLeft ) 131 | 132 | dim surrogate as M_REST.PrivateSurrogate = MessageSurrogate 133 | if surrogate isa object then 134 | surrogate.RaiseSendProgress( self, bytesSent, bytesLeft ) 135 | end if 136 | 137 | End Sub 138 | #tag EndEvent 139 | 140 | 141 | #tag Method, Flags = &h21 142 | Private Sub ClearClassMeta() 143 | if ClassName <> "" and ClassMetaDict isa object and ClassMetaDict.HasKey( ClassName ) then 144 | ClassMetaDict.Remove ClassName 145 | end if 146 | 147 | End Sub 148 | #tag EndMethod 149 | 150 | #tag Method, Flags = &h21 151 | Private Sub ClearReturnProperties() 152 | CreateMeta 153 | 154 | dim meta as M_REST.ClassMeta = MyMeta 155 | if meta is nil or MessageOptions.ReturnPropertyPrefix = "" then 156 | return 157 | end if 158 | 159 | for each entry as Xojo.Core.DictionaryEntry in meta.ReturnPropertiesDict 160 | dim prop as Xojo.Introspection.PropertyInfo = entry.Value 161 | dim propType as text = prop.PropertyType.Name 162 | 163 | if propType = "String()" then 164 | #if not TargetiOS then 165 | dim arr() as string = prop.Value( self ) 166 | redim arr( -1 ) 167 | #endif 168 | 169 | elseif propType = "Text()" then 170 | dim arr() as text = prop.Value( self ) 171 | redim arr( -1 ) 172 | 173 | elseif propType = "Double()" then 174 | dim arr() as double = prop.Value( self ) 175 | redim arr( -1 ) 176 | 177 | elseif propType = "Single()" then 178 | dim arr() as single = prop.Value( self ) 179 | redim arr( -1 ) 180 | 181 | elseif propType = "Currency()" then 182 | dim arr() as currency 183 | redim arr( -1 ) 184 | 185 | elseif propType = "Boolean()" then 186 | dim arr() as boolean = prop.Value( self ) 187 | redim arr( -1 ) 188 | 189 | elseif propType = "Int8()" then 190 | dim arr() as Int8 = prop.Value( self ) 191 | redim arr( -1 ) 192 | 193 | elseif propType = "Int16()" then 194 | dim arr() as Int16 = prop.Value( self ) 195 | redim arr( -1 ) 196 | 197 | elseif propType = "Int32()" then 198 | dim arr() as Int32 = prop.Value( self ) 199 | redim arr( -1 ) 200 | 201 | elseif propType = "Int64()" then 202 | dim arr() as Int64 = prop.Value( self ) 203 | redim arr( -1 ) 204 | 205 | elseif propType = "UInt8()" then 206 | dim arr() as UInt8 = prop.Value( self ) 207 | redim arr( -1 ) 208 | 209 | elseif propType = "UInt16()" then 210 | dim arr() as UInt16 = prop.Value( self ) 211 | redim arr( -1 ) 212 | 213 | elseif propType = "UInt32()" then 214 | dim arr() as UInt32 = prop.Value( self ) 215 | redim arr( -1 ) 216 | 217 | elseif propType = "UInt64()" then 218 | dim arr() as UInt64 = prop.Value( self ) 219 | redim arr( -1 ) 220 | 221 | elseif propType.EndsWith( "()" ) then 222 | // 223 | // Object array 224 | // 225 | dim arr() as object = prop.Value( self ) 226 | redim arr( -1 ) 227 | 228 | elseif propType = "Text" or propType = "String" then 229 | prop.Value( self ) = "" 230 | 231 | elseif propType.Length > 4 and ( propType.BeginsWith( "Int" ) or propType.BeginsWith( "UInt" ) ) then 232 | prop.Value( self ) = 0 233 | 234 | elseif propType = "Double" or propType = "Single" or propType = "Currency" then 235 | prop.Value( self ) = 0.0 236 | 237 | elseif propType = "Boolean" then 238 | prop.Value( self ) = false 239 | 240 | else 241 | // 242 | // Must be an object 243 | // 244 | prop.Value( self ) = nil 245 | 246 | end if 247 | next 248 | End Sub 249 | #tag EndMethod 250 | 251 | #tag Method, Flags = &h0 252 | Sub Constructor() 253 | // Calling the overridden superclass constructor. 254 | Super.Constructor 255 | 256 | CreateMeta 257 | 258 | TimeoutTimer = new Xojo.Core.Timer 259 | TimeoutTimer.Mode = Xojo.Core.Timer.Modes.Off 260 | 261 | AddHandler TimeoutTimer.Action, WeakAddressOf TimeoutTimer_Action 262 | 263 | RaiseEvent Setup 264 | 265 | End Sub 266 | #tag EndMethod 267 | 268 | #tag Method, Flags = &h21 269 | Private Sub CreateMeta() 270 | if ClassMetaDict is nil then 271 | ClassMetaDict = new Xojo.Core.Dictionary 272 | end if 273 | 274 | dim tiSelf as Xojo.Introspection.TypeInfo = Xojo.Introspection.GetType( self ) 275 | ClassName = tiSelf.FullName 276 | dim classMeta as M_REST.ClassMeta = ClassMetaDict.Lookup( className, nil ) 277 | if classMeta isa object then 278 | // 279 | // Already done 280 | // 281 | return 282 | end if 283 | classMeta = new M_REST.ClassMeta 284 | 285 | dim tiBase as Xojo.Introspection.TypeInfo = tiSelf.BaseType 286 | while tiBase.BaseType isa Object and tiBase.BaseType.FullName <> "Xojo.Net.HTTPSocket" 287 | tiBase = tiBase.BaseType 288 | wend 289 | 290 | // 291 | // Get or create the meta for the base class 292 | // 293 | dim baseName as text = tiBase.FullName 294 | dim baseMeta as M_REST.ClassMeta = ClassMetaDict.Lookup( baseName, nil ) 295 | if baseMeta is nil then 296 | baseMeta = new M_REST.ClassMeta 297 | dim dict as Xojo.Core.Dictionary = baseMeta.SendPropertiesDict 298 | 299 | dim props() as Xojo.Introspection.PropertyInfo = tiBase.Properties 300 | for each prop as Xojo.Introspection.PropertyInfo in props 301 | dim propName as text = prop.Name 302 | if prop.CanRead and prop.IsPublic and not prop.IsShared then 303 | dict.Value( propName ) = prop 304 | end if 305 | next 306 | end if 307 | 308 | // 309 | // Fill out the class meta 310 | // 311 | for each prop as Xojo.Introspection.PropertyInfo in tiSelf.Properties 312 | dim propName as text = prop.Name 313 | 314 | if prop.IsShared or not prop.IsPublic then 315 | // 316 | // Doesn't qualify 317 | // 318 | continue for prop 319 | end if 320 | 321 | if baseMeta.SendPropertiesDict.HasKey( propName ) or baseMeta.ReturnPropertiesDict.HasKey( propName ) then 322 | // 323 | // Part of the base so we ignore it 324 | // 325 | continue for prop 326 | end if 327 | 328 | if propName = "Index" then 329 | // 330 | // Something that comes up in a window, so ignore it 331 | // 332 | continue for prop 333 | end if 334 | 335 | dim isReturnProp as boolean 336 | 337 | dim returnPropPrefix as text = MessageOptions.ReturnPropertyPrefix 338 | dim prefixLength as integer = returnPropPrefix.Length 339 | if returnPropPrefix = "" or _ // Can be empty 340 | ( propName.Length > prefixLength and propName.Left( prefixLength ) = returnPropPrefix ) then // Return property 341 | if prop.CanWrite then 342 | classMeta.ReturnPropertiesDict.Value( propName ) = prop 343 | isReturnProp = true 344 | end if 345 | end if 346 | 347 | if not isReturnProp or returnPropPrefix = "" then // Send property 348 | if prop.CanRead then 349 | classMeta.SendPropertiesDict.Value( propName ) = prop 350 | end if 351 | end if 352 | next prop 353 | 354 | classMetaDict.Value( className ) = classMeta 355 | 356 | End Sub 357 | #tag EndMethod 358 | 359 | #tag Method, Flags = &h21 360 | Private Function CreateOutgoingPayload(props() As Xojo.Introspection.PropertyInfo) As Xojo.Core.MemoryBlock 361 | dim result as Xojo.Core.MemoryBlock 362 | 363 | dim json as new Xojo.Core.Dictionary 364 | 365 | for each prop as Xojo.Introspection.PropertyInfo in props 366 | dim propName as text = prop.Name 367 | dim propValue as auto = prop.Value( self ) 368 | 369 | if not RaiseEvent ExcludeFromOutgoingPayload( prop, propName, propValue ) then 370 | json.Value( propName ) = Serialize( propValue ) 371 | end if 372 | next 373 | 374 | if json.Count <> 0 then 375 | dim t as text = Xojo.Data.GenerateJSON( json ) 376 | dim encoding as Xojo.Core.TextEncoding = MessageOptions.ExpectedTextEncoding 377 | result = encoding.ConvertTextToData( t ) 378 | end if 379 | 380 | return result 381 | 382 | End Function 383 | #tag EndMethod 384 | 385 | #tag Method, Flags = &h21 386 | Private Function Deserialize(value As Auto, intoProp As Xojo.Introspection.PropertyInfo, currentValue As Auto) As Auto 387 | dim tiDestination as Xojo.Introspection.TypeInfo = intoProp.PropertyType 388 | dim typeName as text = tiDestination.Name 389 | 390 | if typeName.Length > 2 and typeName.EndsWith( "()" ) then 391 | return DeserializeArray( value, intoProp, currentValue ) 392 | 393 | elseif IsIntrinsicType( typeName ) then 394 | return value 395 | 396 | else 397 | dim objectDict as Xojo.Core.Dictionary = value 398 | return DeserializeObject( objectDict, intoProp ) 399 | 400 | end if 401 | End Function 402 | #tag EndMethod 403 | 404 | #tag Method, Flags = &h21 405 | Private Function DeserializeArray(value As Auto, intoProp As Xojo.Introspection.PropertyInfo, existingArray As Auto) As Auto 406 | dim tiDestination as Xojo.Introspection.TypeInfo = intoProp.PropertyType 407 | dim typeName as text = tiDestination.Name 408 | 409 | dim sourceArr() as auto = value 410 | 411 | select case typeName 412 | case "Text()" 413 | dim arr() as text 414 | try 415 | redim arr( sourceArr.Ubound ) 416 | for i as integer = 0 to sourceArr.Ubound 417 | arr( i ) = sourceArr( i ) 418 | next 419 | catch err as TypeMismatchException 420 | redim arr( -1 ) 421 | end try 422 | return arr 423 | 424 | case "String()" 425 | #if not TargetiOS then 426 | dim arr() as string 427 | try 428 | redim arr( sourceArr.Ubound ) 429 | for i as integer = 0 to sourceArr.Ubound 430 | arr( i ) = sourceArr( i ) 431 | next 432 | catch err as TypeMismatchException 433 | redim arr( -1 ) 434 | end try 435 | return arr 436 | #endif 437 | 438 | case "Boolean()" 439 | dim arr() as boolean 440 | try 441 | redim arr( sourceArr.Ubound ) 442 | for i as integer = 0 to sourceArr.Ubound 443 | arr( i ) = sourceArr( i ) 444 | next 445 | catch err as TypeMismatchException 446 | redim arr( -1 ) 447 | end try 448 | return arr 449 | 450 | case "Currency()" 451 | dim arr() as currency 452 | try 453 | redim arr( sourceArr.Ubound ) 454 | for i as integer = 0 to sourceArr.Ubound 455 | arr( i ) = sourceArr( i ) 456 | next 457 | catch err as TypeMismatchException 458 | redim arr( -1 ) 459 | end try 460 | return arr 461 | 462 | case "Double()" 463 | dim arr() as double 464 | try 465 | redim arr( sourceArr.Ubound ) 466 | for i as integer = 0 to sourceArr.Ubound 467 | arr( i ) = sourceArr( i ) 468 | next 469 | catch err as TypeMismatchException 470 | redim arr( -1 ) 471 | end try 472 | return arr 473 | 474 | case "Single()" 475 | dim arr() as single 476 | try 477 | redim arr( sourceArr.Ubound ) 478 | for i as integer = 0 to sourceArr.Ubound 479 | arr( i ) = sourceArr( i ) 480 | next 481 | catch err as TypeMismatchException 482 | redim arr( -1 ) 483 | end try 484 | return arr 485 | 486 | case "Int8()" 487 | dim arr() as Int8 488 | try 489 | redim arr( sourceArr.Ubound ) 490 | for i as integer = 0 to sourceArr.Ubound 491 | arr( i ) = sourceArr( i ) 492 | next 493 | catch err as TypeMismatchException 494 | redim arr( -1 ) 495 | end try 496 | return arr 497 | 498 | case "Int16()" 499 | dim arr() as Int16 500 | try 501 | redim arr( sourceArr.Ubound ) 502 | for i as integer = 0 to sourceArr.Ubound 503 | arr( i ) = sourceArr( i ) 504 | next 505 | catch err as TypeMismatchException 506 | redim arr( -1 ) 507 | end try 508 | return arr 509 | 510 | case "Int32()" 511 | dim arr() as Int32 512 | try 513 | redim arr( sourceArr.Ubound ) 514 | for i as integer = 0 to sourceArr.Ubound 515 | arr( i ) = sourceArr( i ) 516 | next 517 | catch err as TypeMismatchException 518 | redim arr( -1 ) 519 | end try 520 | return arr 521 | 522 | case "Int64()" 523 | dim arr() as Int64 524 | try 525 | redim arr( sourceArr.Ubound ) 526 | for i as integer = 0 to sourceArr.Ubound 527 | arr( i ) = sourceArr( i ) 528 | next 529 | catch err as TypeMismatchException 530 | redim arr( -1 ) 531 | end try 532 | return arr 533 | 534 | case "Byte()" 535 | dim arr() as byte 536 | try 537 | redim arr( sourceArr.Ubound ) 538 | for i as integer = 0 to sourceArr.Ubound 539 | arr( i ) = sourceArr( i ) 540 | next 541 | catch err as TypeMismatchException 542 | redim arr( -1 ) 543 | end try 544 | return arr 545 | 546 | case "UInt8()" 547 | dim arr() as UInt8 548 | try 549 | redim arr( sourceArr.Ubound ) 550 | for i as integer = 0 to sourceArr.Ubound 551 | arr( i ) = sourceArr( i ) 552 | next 553 | catch err as TypeMismatchException 554 | redim arr( -1 ) 555 | end try 556 | return arr 557 | 558 | case "UInt16()" 559 | dim arr() as UInt16 560 | try 561 | redim arr( sourceArr.Ubound ) 562 | for i as integer = 0 to sourceArr.Ubound 563 | arr( i ) = sourceArr( i ) 564 | next 565 | catch err as TypeMismatchException 566 | redim arr( -1 ) 567 | end try 568 | return arr 569 | 570 | case "UInt32()" 571 | dim arr() as UInt32 572 | try 573 | redim arr( sourceArr.Ubound ) 574 | for i as integer = 0 to sourceArr.Ubound 575 | arr( i ) = sourceArr( i ) 576 | next 577 | catch err as TypeMismatchException 578 | redim arr( -1 ) 579 | end try 580 | return arr 581 | 582 | case "UInt64()" 583 | dim arr() as UInt64 584 | try 585 | redim arr( sourceArr.Ubound ) 586 | for i as integer = 0 to sourceArr.Ubound 587 | arr( i ) = sourceArr( i ) 588 | next 589 | catch err as TypeMismatchException 590 | redim arr( -1 ) 591 | end try 592 | return arr 593 | 594 | case "Integer()" 595 | dim arr() as integer 596 | try 597 | redim arr( sourceArr.Ubound ) 598 | for i as integer = 0 to sourceArr.Ubound 599 | arr( i ) = sourceArr( i ) 600 | next 601 | catch err as TypeMismatchException 602 | redim arr( -1 ) 603 | end try 604 | return arr 605 | 606 | case "Auto()" 607 | return value 608 | 609 | case "Variant()" 610 | #if not TargetiOS then 611 | dim arr() as variant 612 | redim arr( sourceArr.Ubound ) 613 | for i as integer = 0 to sourceArr.Ubound 614 | arr( i ) = sourceArr( i ) 615 | next 616 | return arr 617 | #endif 618 | 619 | case else 620 | // 621 | // Must be an object 622 | // 623 | dim arr() as object 624 | try 625 | arr = existingArray 626 | redim arr( sourceArr.Ubound ) 627 | 628 | for i as integer = 0 to sourceArr.Ubound 629 | arr( i ) = Deserialize( sourceArr( i ), intoProp, existingArray ) 630 | next 631 | catch err as TypeMismatchException 632 | redim arr( -1 ) 633 | end try 634 | return arr 635 | 636 | end select 637 | End Function 638 | #tag EndMethod 639 | 640 | #tag Method, Flags = &h21 641 | Private Function DeserializeDate(value As Text, intoProp As Xojo.Introspection.PropertyInfo) As Auto 642 | // 643 | // We are expecting the ISO 8601 format 644 | // as a date or date and time. 645 | // 646 | // https://en.wikipedia.org/wiki/ISO_8601 647 | // 648 | 649 | dim parts() as text = value.Split( "T" ) 650 | if parts.Ubound = -1 or parts.Ubound > 1 then 651 | // 652 | // We don't recognize this format 653 | // 654 | return nil 655 | end if 656 | 657 | dim datePart as text = parts( 0 ) 658 | dim dateParts() as text = datePart.Split( "-" ) 659 | if dateParts.Ubound <> 2 then 660 | return nil 661 | end if 662 | 663 | dim year as integer = Integer.FromText( dateParts( 0 ) ) 664 | dim month as integer = Integer.FromText( dateParts( 1 ) ) 665 | dim day as integer = Integer.FromText( dateParts( 2 ) ) 666 | 667 | // 668 | // See if there is a time 669 | // 670 | dim hour as integer 671 | dim minute as integer 672 | dim second as integer 673 | 674 | dim tz as Xojo.Core.TimeZone = Xojo.Core.TimeZone.Current 675 | dim tzHours as double = tz.SecondsFromGMT / 3600.0 676 | 677 | if parts.Ubound = 1 then 678 | dim timePart as text = parts( 1 ) 679 | dim timeParts() as text 680 | dim tzPart as text 681 | 682 | select case true 683 | case timePart.IndexOf( "Z" ) <> -1 684 | timeParts = timePart.Split( "Z" ) 685 | timePart = timeParts( 0 ) 686 | tzPart = "0" 687 | 688 | case timePart.IndexOf( "-" ) <> -1 689 | timeParts = timePart.Split( "-" ) 690 | timePart = timeParts( 0 ) 691 | tzPart = "-" + timeParts( 1 ) 692 | 693 | case timePart.IndexOf( "+" ) <> -1 694 | timeParts = timePart.Split( "+" ) 695 | timePart = timeParts( 0 ) 696 | tzPart = timeParts( 1 ) 697 | 698 | end select 699 | 700 | // 701 | // The time will either be in HH:MM:SS format or HHMMSS format 702 | // 703 | timePart = timePart.ReplaceAll( ":", "" ) 704 | if timePart.Length = 6 then 705 | hour = Integer.FromText( timePart.Left( 2 ) ) 706 | minute = Integer.FromText( timePart.Mid( 2, 2 ) ) 707 | second = Integer.FromText( timePart.Right( 2 ) ) 708 | 709 | // 710 | // Process the timezone, maybe 711 | // 712 | if MessageOptions.AdjustDatesForTimeZone then 713 | dim tzParts() as text = tzPart.Split( ":" ) 714 | if tzParts.Ubound = 1 then 715 | tzHours = Integer.FromText( tzParts( 0 ) ) + ( Integer.FromText( tzParts( 1 ) ) / 60.0 ) 716 | tz = new Xojo.Core.TimeZone( tzHours * 3600.0 ) 717 | end if 718 | end if 719 | 720 | end if 721 | end if 722 | 723 | // 724 | // Create the object 725 | // 726 | select case intoProp.PropertyType.FullName 727 | case "Xojo.Core.Date" 728 | dim d as new Xojo.Core.Date( year, month, day, hour, minute, second, 0, tz ) 729 | return d 730 | 731 | case else 732 | #if not TargetiOS then 733 | dim d as new Date( year, month, day, hour, minute, second, tzHours ) 734 | return d 735 | #endif 736 | 737 | end select 738 | End Function 739 | #tag EndMethod 740 | 741 | #tag Method, Flags = &h21 742 | Private Function DeserializeDictionary(value As Xojo.Core.Dictionary, intoProp As Xojo.Introspection.PropertyInfo) As Auto 743 | select case intoProp.PropertyType.FullName 744 | case "Xojo.Core.Dictionary" 745 | dim dict as new Xojo.Core.Dictionary 746 | for each entry as Xojo.Core.DictionaryEntry in value 747 | dict.Value( entry.Key ) = entry.Value 748 | next 749 | return dict 750 | 751 | case "Dictionary" 752 | #if not TargetiOS then 753 | dim dict as new Dictionary 754 | for each entry as Xojo.Core.DictionaryEntry in value 755 | dict.Value( entry.Key ) = entry.Value 756 | next 757 | return dict 758 | #endif 759 | 760 | end select 761 | End Function 762 | #tag EndMethod 763 | 764 | #tag Method, Flags = &h21 765 | Private Function DeserializeObject(value As Auto, intoProp As Xojo.Introspection.PropertyInfo) As Object 766 | dim tiObject as Xojo.Introspection.TypeInfo = intoProp.PropertyType 767 | dim typeName as text = tiObject.Name 768 | 769 | select case typeName 770 | case "Dictionary", "Xojo.Core.Dictionary" 771 | return DeserializeDictionary( value, intoProp ) 772 | 773 | case "Date", "Xojo.Core.Date" 774 | return DeserializeDate( value, intoProp ) 775 | 776 | case else 777 | // 778 | // Have to create a new object to return 779 | // 780 | dim c as Xojo.Introspection.ConstructorInfo = GetZeroParamConstructor( intoProp.PropertyType ) 781 | if c isa object then 782 | dim o as object = c.Invoke 783 | 784 | // 785 | // Create a dictionary of the object's properties 786 | // 787 | dim propsDict as new Xojo.Core.Dictionary 788 | for each prop as Xojo.Introspection.PropertyInfo in tiObject.Properties 789 | if prop.CanWrite and prop.IsPublic and not prop.IsShared then 790 | propsDict.Value( prop.Name ) = prop 791 | end if 792 | next prop 793 | 794 | if propsDict.Count <> 0 then 795 | JSONObjectToProps( value, propsDict, "", o ) 796 | end if 797 | 798 | return o 799 | end if 800 | end select 801 | End Function 802 | #tag EndMethod 803 | 804 | #tag Method, Flags = &h21 805 | Private Sub Destructor() 806 | if TimeoutTimer isa Object then 807 | TimeoutTimer.Mode = Xojo.Core.Timer.Modes.Off 808 | RemoveHandler TimeoutTimer.Action, WeakAddressOf TimeoutTimer_Action 809 | TimeoutTimer = nil 810 | end if 811 | 812 | // 813 | // We don't bother removing the message from the MessageSurrogate here. 814 | // Why? Well, if the surrogate still has the message, this 815 | // Destructor will never fire anyway. 816 | // 817 | End Sub 818 | #tag EndMethod 819 | 820 | #tag Method, Flags = &h0 821 | Sub Disconnect() 822 | if IsConnected then 823 | mIsConnected = false 824 | TimeoutTimer.Mode = Xojo.Core.Timer.Modes.Off 825 | super.Disconnect 826 | end if 827 | 828 | dim surrogate as M_REST.PrivateSurrogate = MessageSurrogate 829 | if surrogate isa object then 830 | surrogate.RemoveMessage self 831 | MessageSurrogate = nil 832 | end if 833 | 834 | 835 | End Sub 836 | #tag EndMethod 837 | 838 | #tag Method, Flags = &h21 839 | Private Shared Function IsIntrinsicType(propType As Text) As Boolean 840 | static types() as text 841 | 842 | if types.Ubound = -1 then 843 | types = array( _ 844 | "Int8", "Int16", "Int32", "Int64", _ 845 | "Byte", "UInt8", "UInt16", "UInt32", "UInt64", _ 846 | "Single", "Double", "Currency", _ 847 | "String", "Text", _ 848 | "Boolean" _ 849 | ) 850 | 851 | // 852 | // Add the array versions 853 | // 854 | dim lastIndex as integer = types.Ubound 855 | for i as integer = 0 to lastIndex 856 | types.Append types( i ) + "()" 857 | next 858 | end if 859 | 860 | return types.IndexOf( propType ) <> -1 861 | 862 | End Function 863 | #tag EndMethod 864 | 865 | #tag Method, Flags = &h21 866 | Private Sub JSONObjectToProps(json As Xojo.Core.Dictionary, propsDict As Xojo.Core.Dictionary, propPrefix As Text, hostObject As Object) 867 | for each entry as Xojo.Core.DictionaryEntry in json 868 | dim returnPropName as text = propPrefix + entry.Key 869 | if not propsDict.HasKey( returnPropName ) then 870 | continue for entry 871 | end if 872 | 873 | dim prop as Xojo.Introspection.PropertyInfo = propsDict.Value( returnPropName ) 874 | 875 | dim value as Auto = entry.Value 876 | 877 | if not RaiseEvent IncomingPayloadValueToProperty( value, prop, hostObject ) then 878 | try 879 | value = Deserialize( value, prop, prop.Value( hostObject ) ) 880 | prop.Value( hostObject ) = value 881 | 882 | catch err as TypeMismatchException 883 | // 884 | // Didn't work, move on 885 | // 886 | end try 887 | 888 | end if 889 | next 890 | 891 | End Sub 892 | #tag EndMethod 893 | 894 | #tag Method, Flags = &h21 895 | Private Sub PrepareToSend() 896 | mIsConnected = true 897 | RequestSentMicroseconds = Microseconds 898 | ResponseReceivedMicroseconds = -1.0 899 | 900 | TimeoutTimer.Period = MessageOptions.TimeOutSeconds * 1000 901 | TimeoutTimer.Mode = Xojo.Core.Timer.Modes.Multiple 902 | 903 | End Sub 904 | #tag EndMethod 905 | 906 | #tag Method, Flags = &h21 907 | Private Function ProcessImagePayload(payload As Xojo.Core.MemoryBlock) As Auto 908 | dim result as Auto 909 | 910 | #if TargetiOS then 911 | #pragma error "Finish this!" 912 | 913 | #else 914 | 915 | // 916 | // Have to use the classic MemoryBlock 917 | // 918 | dim mbTemp as MemoryBlock = payload.Data 919 | dim p as Picture = Picture.FromData( mbTemp.StringValue( 0, payload.Size ) ) 920 | result = p 921 | 922 | #endif 923 | 924 | if result <> nil then 925 | // 926 | // It's got something, so let's try to store it 927 | // 928 | 929 | dim meta as M_REST.ClassMeta = MyMeta 930 | dim tiResult as Xojo.Introspection.TypeInfo = Xojo.Introspection.GetType( result ) 931 | dim matchType as text = tiResult.Name 932 | 933 | dim picProps() as Xojo.Introspection.PropertyInfo 934 | 935 | for each entry as Xojo.Core.DictionaryEntry in meta.ReturnPropertiesDict 936 | dim prop as Xojo.Introspection.PropertyInfo = entry.Value 937 | if prop.PropertyType.Name = matchType then 938 | picProps.Append prop 939 | end if 940 | next 941 | 942 | if picProps.Ubound = 0 then 943 | picProps( 0 ).Value( self ) = result 944 | end if 945 | end if 946 | 947 | return result 948 | 949 | End Function 950 | #tag EndMethod 951 | 952 | #tag Method, Flags = &h21 953 | Private Sub ProcessJSONPayload(payload As Auto) 954 | CreateMeta // REALLY shouldn't be needed, but let's make sure 955 | 956 | dim returnProps as Xojo.Core.Dictionary = MyMeta.ReturnPropertiesDict 957 | 958 | // 959 | // If the JSON is just an array, see if there is only one return property 960 | // and it's an array. If so, copy the items into that. 961 | // 962 | 963 | dim tiPayload as Xojo.Introspection.TypeInfo = Xojo.Introspection.GetType( payload ) 964 | if tiPayload.Name.Length > 2 and tiPayload.Name.EndsWith( "()" ) then 965 | 966 | if returnProps.Count = 1 then 967 | dim prop as Xojo.Introspection.PropertyInfo 968 | for each entry as Xojo.Core.DictionaryEntry in returnProps 969 | prop = entry.Value 970 | next 971 | 972 | try 973 | prop.Value( self ) = DeserializeArray( payload, prop, prop.Value( self ) ) 974 | catch err as TypeMismatchException 975 | // 976 | // Oh well, we tried 977 | // 978 | end try 979 | end if 980 | 981 | else 982 | // 983 | // It's an object, so it will be case-sensitive. 984 | // Cycle through the object and match it against the returnProps 985 | // dictionary that is not case-sensitive 986 | // 987 | 988 | dim json as Xojo.Core.Dictionary = payload 989 | dim returnPropPrefix as text = MessageOptions.ReturnPropertyPrefix 990 | JSONObjectToProps( json, returnProps, returnPropPrefix, self ) 991 | 992 | end if 993 | End Sub 994 | #tag EndMethod 995 | 996 | #tag Method, Flags = &h21 997 | Private Function ProcessPayload(payload As Xojo.Core.MemoryBlock) As Auto 998 | dim result as Auto 999 | 1000 | dim indicatedContentType as text = self.ResponseHeader( "Content-Type" ) 1001 | 1002 | dim parts() as text = indicatedContentType.Split( "/" ) 1003 | dim indicatedType as text = if( parts.Ubound <> -1, parts( 0 ), "" ) 1004 | dim indicatedSubtype as text = if( parts.Ubound > 0, indicatedContentType.Mid( indicatedContentType.IndexOf( "/" ) + 1 ), "" ) 1005 | 1006 | if indicatedType = "image" then 1007 | try 1008 | result = ProcessImagePayload( payload ) 1009 | catch err as RuntimeException 1010 | if err isa EndException or err isa ThreadEndException then 1011 | raise err 1012 | end if 1013 | indicatedType = "" 1014 | indicatedSubtype = "" 1015 | end try 1016 | end if 1017 | 1018 | if indicatedType = "text" or _ 1019 | ( indicatedSubtype.Length >= 4 and indicatedSubtype.BeginsWith( "json" ) ) or _ 1020 | ( indicatedSubtype.Length >= 3 and indicatedSubtype.BeginsWith( "xml" ) ) or _ 1021 | indicatedType = "" then 1022 | try 1023 | result = ProcessTextPayload( payload, indicatedSubtype ) 1024 | catch err as RuntimeException 1025 | if err isa EndException or err isa ThreadEndException then 1026 | raise err 1027 | end if 1028 | indicatedType = "" 1029 | indicatedSubtype = "" 1030 | end try 1031 | end if 1032 | 1033 | if result = nil then 1034 | // 1035 | // The indicated type was wrong or couldn't be handled properly. 1036 | // In either case, just pass it on. 1037 | // 1038 | result = payload 1039 | end if 1040 | 1041 | return result 1042 | 1043 | 1044 | End Function 1045 | #tag EndMethod 1046 | 1047 | #tag Method, Flags = &h21 1048 | Private Function ProcessTextPayload(payload As Xojo.Core.MemoryBlock, subtype As Text) As Auto 1049 | dim result as Auto 1050 | 1051 | dim encoding as Xojo.Core.TextEncoding = MessageOptions.ExpectedTextEncoding 1052 | 1053 | // 1054 | // See if an encoding is indicated 1055 | // 1056 | if subtype <> "" then 1057 | dim parts() as text = subtype.Split( ";" ) 1058 | if parts.Ubound > 0 then 1059 | 1060 | dim pairs as new Xojo.Core.Dictionary 1061 | for each part as text in parts 1062 | dim subparts() as text = part.Split( "=" ) 1063 | if subparts.Ubound = 1 then 1064 | pairs.Value( subparts( 0 ).Trim ) = subparts( 1 ).Trim 1065 | end if 1066 | next 1067 | 1068 | if pairs.HasKey( "charset" ) then 1069 | try 1070 | encoding = Xojo.Core.TextEncoding.FromIANAName( pairs.Value( "charset" ) ) 1071 | catch err as RuntimeException 1072 | if err isa EndException or err isa ThreadEndException then 1073 | raise err 1074 | end if 1075 | end try 1076 | end if 1077 | 1078 | end if 1079 | end if 1080 | 1081 | dim textValue as text = encoding.ConvertDataToText( payload ) 1082 | // 1083 | // If that crashes, the caller will handle it 1084 | // 1085 | 1086 | // 1087 | // Try to figure it out 1088 | // 1089 | 1090 | // 1091 | // JSON? 1092 | // 1093 | dim json as Xojo.Core.Dictionary 1094 | if subtype <> "xml" then 1095 | // 1096 | // We are going to try anything since the header could be wrong 1097 | // 1098 | try 1099 | json = Xojo.Data.ParseJSON( textValue ) 1100 | subtype = "json" 1101 | result = json 1102 | catch err as RuntimeException 1103 | if err isa EndException or err isa ThreadEndException then 1104 | raise err 1105 | end if 1106 | end try 1107 | end if 1108 | 1109 | #if not TargetiOS then 1110 | // 1111 | // XML? 1112 | // 1113 | dim xml as XMLDocument 1114 | if subtype = "" or subtype = "xml" then 1115 | try 1116 | xml = new XmlDocument( textValue ) 1117 | result = xml 1118 | subtype = "xml" 1119 | catch err as XmlException 1120 | // 1121 | // Do nothing 1122 | // 1123 | end try 1124 | end if 1125 | #endif 1126 | 1127 | if result = nil then 1128 | result = textValue 1129 | elseif json isa Xojo.Core.Dictionary then 1130 | // 1131 | // It's JSON, so let's try to parse it into the return 1132 | // properties 1133 | // 1134 | ProcessJSONPayload( json ) 1135 | end if 1136 | 1137 | return result 1138 | 1139 | End Function 1140 | #tag EndMethod 1141 | 1142 | #tag Method, Flags = &h21 1143 | Private Shared Function PublicPropertiesToDictionary(ti As Xojo.Introspection.TypeInfo) As Xojo.Core.Dictionary 1144 | dim dict as new Xojo.Core.Dictionary 1145 | 1146 | dim props() as Xojo.Introspection.PropertyInfo = ti.Properties 1147 | for each prop as Xojo.Introspection.PropertyInfo in props 1148 | if prop.CanRead and prop.IsPublic and not prop.IsShared then 1149 | dict.Value( prop.Name ) = prop 1150 | end if 1151 | next 1152 | 1153 | return dict 1154 | End Function 1155 | #tag EndMethod 1156 | 1157 | #tag Method, Flags = &h0 1158 | Shared Function RESTTypeToHTTPAction(type As RESTTypes) As Text 1159 | select case type 1160 | case RESTTypes.Read, RESTTypes.GET 1161 | return kActionGet 1162 | 1163 | case RESTTypes.Create, RESTTypes.Authenticate, RESTTypes.POST 1164 | return kActionPost 1165 | 1166 | case RESTTypes.DELETE 1167 | return kActionDelete 1168 | 1169 | case RESTTypes.UpdateReplace, RESTTypes.PUT 1170 | return kActionPut 1171 | 1172 | case RESTTypes.UpdateModify, RESTTypes.PATCH 1173 | return kActionPatch 1174 | 1175 | case RESTTypes.OPTIONS 1176 | return kActionOptions 1177 | 1178 | case else 1179 | return kActionUnknown 1180 | 1181 | end select 1182 | End Function 1183 | #tag EndMethod 1184 | 1185 | #tag Method, Flags = &h0 1186 | Sub Send(surrogate As RESTMessageSurrogate_MTC = Nil) 1187 | RequestStartedMicroseconds = microseconds 1188 | ReceiveFinishedMicroseconds = -1.0 1189 | 1190 | dim action as text = HTTPAction 1191 | if action = kActionUnknown then 1192 | raise new M_REST.RESTException( "REST type was not specified" ) 1193 | end if 1194 | 1195 | CreateMeta // Just in case 1196 | dim meta as M_REST.ClassMeta = MyMeta 1197 | 1198 | dim url as text = RaiseEvent GetURLPattern 1199 | url = url.Trim 1200 | 1201 | // 1202 | // Parse the URL 1203 | // 1204 | dim urlPropNames() as text 1205 | dim payloadProps() as Xojo.Introspection.PropertyInfo 1206 | 1207 | for each entry as Xojo.Core.DictionaryEntry in meta.SendPropertiesDict 1208 | dim prop as Xojo.Introspection.PropertyInfo = entry.Value 1209 | dim propName as text = prop.Name 1210 | 1211 | dim marker as text = ":" + prop.Name 1212 | if url.IndexOf( marker ) = -1 then 1213 | payloadProps.Append prop 1214 | else 1215 | 1216 | urlPropNames.Append propName 1217 | dim value as auto = prop.Value( self ) 1218 | 1219 | // 1220 | // Get the text version of the value 1221 | // 1222 | dim tiValue as Xojo.Introspection.TypeInfo = Xojo.Introspection.GetType( value ) 1223 | dim textValue as text 1224 | 1225 | select case tiValue.Name 1226 | case "Text" 1227 | // 1228 | // Already good 1229 | // 1230 | textValue = value 1231 | 1232 | case "Integer", "Int8", "Int16", "Int32", "Int64" 1233 | dim i as Int64 = value 1234 | textValue = i.ToText 1235 | 1236 | case "UInt8", "UInt16", "UInt32", "UInt64", "Byte" 1237 | dim i as UInt64 = value 1238 | textValue = i.ToText 1239 | 1240 | case "Double", "Single", "Currency" 1241 | dim d as double = value 1242 | textValue = d.ToText 1243 | 1244 | case "String" 1245 | #if not TargetiOS then 1246 | dim s as string = value 1247 | textValue = s.ToText 1248 | #endif 1249 | 1250 | case "Boolean" 1251 | const kTrueValue as text = "true" 1252 | const kFalseValue as text = "false" 1253 | 1254 | dim b as boolean = value 1255 | textValue = if( b, kTrueValue, kFalseValue ) 1256 | 1257 | case else 1258 | if value isa M_REST.TextProvider then 1259 | textValue = M_REST.TextProvider( value ).ConvertToText 1260 | else 1261 | raise new M_REST.RESTException( "The property " + propName + " cannot be converted to Text" ) 1262 | end if 1263 | end select 1264 | 1265 | url = url.ReplaceAll( marker, textValue ) 1266 | end if 1267 | next 1268 | 1269 | dim payload as Xojo.Core.MemoryBlock 1270 | if action <> kActionGet and payloadProps.Ubound <> -1 and MessageOptions.SendWithPayloadIfAvailable then 1271 | payload = CreateOutgoingPayload( payloadProps ) 1272 | end if 1273 | 1274 | dim mimeType as text = "application/json" 1275 | if RaiseEvent CancelSend( url, action, payload, mimeType ) then 1276 | return 1277 | end if 1278 | 1279 | if payload isa object then 1280 | if mimeType = "" then 1281 | Raise new M_REST.RESTException( "No MIME type specified" ) 1282 | end if 1283 | 1284 | SetRequestContent payload, mimeType 1285 | end if 1286 | 1287 | MessageSurrogate = surrogate 1288 | Send action, url 1289 | 1290 | if surrogate isa object then 1291 | PrivateSurrogate(surrogate).RaiseSent self 1292 | end if 1293 | 1294 | End Sub 1295 | #tag EndMethod 1296 | 1297 | #tag Method, Flags = &h1 1298 | Protected Sub Send(method as Text, url as Text) 1299 | // 1300 | // Disable external access to this 1301 | // 1302 | 1303 | PrepareToSend 1304 | super.Send( method, url ) 1305 | 1306 | End Sub 1307 | #tag EndMethod 1308 | 1309 | #tag Method, Flags = &h1 1310 | Protected Sub Send(method as Text, url as Text, file as Xojo.IO.FolderItem) 1311 | // 1312 | // Disable external access to this 1313 | // 1314 | 1315 | PrepareToSend 1316 | super.Send( method, url, file ) 1317 | End Sub 1318 | #tag EndMethod 1319 | 1320 | #tag Method, Flags = &h1 1321 | Protected Function Serialize(value As Auto) As Auto 1322 | dim ti as Xojo.Introspection.TypeInfo = Xojo.Introspection.GetType( value ) 1323 | if ti is nil then 1324 | return nil 1325 | end if 1326 | 1327 | dim type as text = ti.Name 1328 | if type.Length > 2 and type.EndsWith( "()" ) then 1329 | return SerializeArray( value, ti ) 1330 | 1331 | elseif type = "String" then 1332 | #if not TargetiOS then 1333 | dim s as string = value 1334 | dim t as text = s.ToText 1335 | return t 1336 | #endif 1337 | 1338 | elseif type = "Currency" then 1339 | dim c as currency = value 1340 | dim d as double = c 1341 | return d 1342 | 1343 | elseif IsIntrinsicType( type ) then 1344 | return value 1345 | 1346 | else 1347 | return SerializeObject( value, ti ) 1348 | 1349 | end if 1350 | 1351 | End Function 1352 | #tag EndMethod 1353 | 1354 | #tag Method, Flags = &h21 1355 | Private Function SerializeArray(value As Auto, ti As Xojo.Introspection.TypeInfo) As Auto 1356 | if ti.Name = "String()" then 1357 | // 1358 | // Convert the string to text to make sure JSON can handle it 1359 | // 1360 | #if not TargetiOS then 1361 | dim arr() as string = value 1362 | dim result() as text 1363 | redim result( arr.Ubound ) 1364 | for i as integer = 0 to arr.Ubound 1365 | result( i ) = arr( i ).ToText 1366 | next i 1367 | return result 1368 | #endif 1369 | 1370 | elseif ti.Name = "Currency()" then 1371 | // 1372 | // JSON can't handle currency so convert to a double 1373 | // 1374 | dim arr() as currency = value 1375 | dim result() as double 1376 | redim result( arr.Ubound ) 1377 | for i as integer = 0 to arr.Ubound 1378 | result( i ) = arr( i ) 1379 | next 1380 | return result 1381 | 1382 | elseif IsIntrinsicType( ti.Name ) then 1383 | // 1384 | // It's another basic type so just return it 1385 | // 1386 | return value 1387 | 1388 | else // It's some object array 1389 | dim arr() as object = value 1390 | dim result() as auto 1391 | redim result( arr.Ubound ) 1392 | for i as integer = 0 to arr.Ubound 1393 | result( i ) = Serialize( arr( i ) ) 1394 | next 1395 | return result 1396 | 1397 | end if 1398 | 1399 | End Function 1400 | #tag EndMethod 1401 | 1402 | #tag Method, Flags = &h21 1403 | Private Function SerializeDate(d As Xojo.Core.Date) As Text 1404 | // 1405 | // Returns ISO 8601 format 1406 | // 1407 | // https://en.wikipedia.org/wiki/ISO_8601 1408 | // 1409 | 1410 | 1411 | dim result as text 1412 | 1413 | if MessageOptions.AdjustDatesForTimeZone then 1414 | dim tz as Xojo.Core.TimeZone = d.TimeZone 1415 | dim interval as new Xojo.Core.DateInterval( 0, 0, 0, 0, 0, tz.SecondsFromGMT ) 1416 | d = d - interval 1417 | end if 1418 | 1419 | dim locale as Xojo.Core.Locale = Xojo.Core.Locale.Current 1420 | 1421 | result = d.Year.ToText( locale, "0000" ) + "-" + d.Month.ToText( locale, "00" ) + "-" + d.Day.ToText( locale, "00" ) 1422 | result = result + "T" + d.Hour.ToText( locale, "00" ) + ":" + d.Minute.ToText( locale, "00" ) + ":" + _ 1423 | d.Second.ToText( locale, "00" ) + "Z" 1424 | 1425 | return result 1426 | 1427 | End Function 1428 | #tag EndMethod 1429 | 1430 | #tag Method, Flags = &h21 1431 | Private Function SerializeDictionary(dict As Xojo.Core.Dictionary) As Xojo.Core.Dictionary 1432 | dim result as new Xojo.Core.Dictionary 1433 | 1434 | for each entry as Xojo.Core.DictionaryEntry in dict 1435 | result.Value( entry.Key ) = Serialize( entry.Value ) 1436 | next 1437 | 1438 | return result 1439 | 1440 | End Function 1441 | #tag EndMethod 1442 | 1443 | #tag Method, Flags = &h21 1444 | Private Function SerializeObject(o As Object, ti As Xojo.Introspection.TypeInfo) As Auto 1445 | // 1446 | // See if the subclass wants to tackle this 1447 | // 1448 | if true then // Scope 1449 | dim autoResult as Auto = RaiseEvent ObjectToJSON( o, ti ) 1450 | if autoResult <> nil then 1451 | return autoResult // *** EARLY EXIT 1452 | end if 1453 | end if 1454 | 1455 | 1456 | #if not TargetiOS then 1457 | if o isa Dictionary then 1458 | // 1459 | // We are going to do this here 1460 | // 1461 | dim result as new Xojo.Core.Dictionary 1462 | 1463 | dim d as Dictionary = Dictionary( o ) 1464 | dim keys() as variant = d.Keys 1465 | dim values() as variant = d.Values 1466 | for i as integer = 0 to keys.Ubound 1467 | result.Value( keys( i ) ) = Serialize( values( i ) ) 1468 | next 1469 | return result // *** EARLY EXIT 1470 | end if 1471 | 1472 | if o isa Date then 1473 | // 1474 | // Convert it to a new Date 1475 | // 1476 | dim d as Date = Date( o ) 1477 | dim tz as new Xojo.Core.TimeZone( d.GMTOffset * 60 * 60 ) 1478 | o = new Xojo.Core.Date( d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second, 0, tz ) 1479 | end if 1480 | #endif 1481 | 1482 | if o isa Xojo.Core.Date then 1483 | return SerializeDate( Xojo.Core.Date( o ) ) // *** EARLY EXIT 1484 | else 1485 | dim result as new Xojo.Core.Dictionary 1486 | 1487 | for each prop as Xojo.Introspection.PropertyInfo in ti.Properties 1488 | if prop.IsPublic and prop.CanRead and not prop.IsShared then 1489 | result.Value( prop.Name ) = Serialize( prop.Value( o ) ) 1490 | end if 1491 | next 1492 | 1493 | return result 1494 | end if 1495 | 1496 | End Function 1497 | #tag EndMethod 1498 | 1499 | #tag Method, Flags = &h21 1500 | Private Sub TimeoutTimer_Action(sender As Xojo.Core.Timer) 1501 | dim surrogate as M_REST.PrivateSurrogate = MessageSurrogate 1502 | 1503 | if IsConnected then 1504 | if RaiseEvent ContinueWaiting or (surrogate isa object and surrogate.RaiseContinueWaiting( self ) ) then 1505 | // 1506 | // One of these wanted to continue waiting 1507 | // 1508 | else 1509 | self.Disconnect 1510 | end if 1511 | end if 1512 | 1513 | sender.Mode = Xojo.Core.Timer.Modes.Off 1514 | if IsConnected then 1515 | sender.Mode = Xojo.Core.Timer.Modes.Multiple 1516 | end if 1517 | 1518 | End Sub 1519 | #tag EndMethod 1520 | 1521 | 1522 | #tag Hook, Flags = &h0 1523 | Event AuthenticationRequired(realm As Text, ByRef username As Text, ByRef password As Text) As Boolean 1524 | #tag EndHook 1525 | 1526 | #tag Hook, Flags = &h0, Description = 4C617374206368616E636520746F2063616E63656C20612073656E64206F72206D6F64696679207468652076616C7565732069742077696C6C207573652E 1527 | Event CancelSend(ByRef url As Text, ByRef httpAction As Text, ByRef payload As Xojo.Core.MemoryBlock, ByRef payloadMIMEType As Text) As Boolean 1528 | #tag EndHook 1529 | 1530 | #tag Hook, Flags = &h0, Description = 546865206D6573736167652068617320657863656564207468652074696D652073657420696E204F7074696F6E732E54696D656F75745365636F6E64732E2052657475726E205472756520746F20616C6C6F7720746865206D65737361676520746F206B6565702077616974696E672E 1531 | Event ContinueWaiting() As Boolean 1532 | #tag EndHook 1533 | 1534 | #tag Hook, Flags = &h0, Description = 54686520736F636B65742068617320646973636F6E6E65637465642E 1535 | Event Disconnected() 1536 | #tag EndHook 1537 | 1538 | #tag Hook, Flags = &h0, Description = 416E206572726F7220686173206F636375727265642E 1539 | Event Error(msg As Text) 1540 | #tag EndHook 1541 | 1542 | #tag Hook, Flags = &h0, Description = 4578636C75646520612070726F70657274792066726F6D20746865206F7574676F696E67207061796C6F6164207468617420776F756C64206F746865727769736520626520696E636C756465642C206F72206368616E6765207468652070726F7065727479206E616D6520616E642F6F722076616C756520746861742077696C6C20626520757365642E 1543 | Event ExcludeFromOutgoingPayload(prop As Xojo.Introspection.PropertyInfo, ByRef propName As Text, ByRef propValue As Auto) As Boolean 1544 | #tag EndHook 1545 | 1546 | #tag Hook, Flags = &h0, Description = 5468652052455354207479706520746F2075736520666F72207468697320636F6E6E656374696F6E2E204966206E6F7420696D706C656D656E7465642C2044656661756C7452455354547970652077696C6C206265207573656420696E73746561642E 1547 | Event GetRESTType() As RESTTypes 1548 | #tag EndHook 1549 | 1550 | #tag Hook, Flags = &h0, Description = 5468652055524C207061747465726E20746F2075736520666F722074686520636F6E6E656374696F6E2E2043616E20696E636C7564652070726F7065727479206E616D657320746861742077696C6C20626520737562737469747574656420666F722076616C75652C20652E672E2C0A0A687474703A2F2F7777772E6578616D706C652E636F6D2F6765742F3A69643F6E616D653D3A6E616D650A0A3A696420616E64203A6E616D652077696C6C206265207265706C616365642062792070726F70657274696573206F66207468652073616D65206E616D652E 1551 | Event GetURLPattern() As Text 1552 | #tag EndHook 1553 | 1554 | #tag Hook, Flags = &h0 1555 | Event HeadersReceived(url As Text, httpStatus As Integer) 1556 | #tag EndHook 1557 | 1558 | #tag Hook, Flags = &h0, Description = 4D616E75616C6C792073746F72652074686520696E636F6D696E67207061796C6F61642076616C756520617320646573697265642E2052657475726E205472756520746F2070726576656E7420667572746865722070726F63657373696E67206F6E20746861742076616C75652E 1559 | Event IncomingPayloadValueToProperty(value As Auto, prop As Xojo.Introspection.PropertyInfo, hostObject As Object) As Boolean 1560 | #tag EndHook 1561 | 1562 | #tag Hook, Flags = &h0, Description = 4D616E75616C6C7920636F6E7665727420616E206F626A65637420746F204A534F4E20666F7220696E636C7573696F6E20696E20746865206F7574676F696E67207061796C6F61642E 1563 | Event ObjectToJSON(o As Object, typeInfo As Xojo.Introspection.TypeInfo) As Auto 1564 | #tag EndHook 1565 | 1566 | #tag Hook, Flags = &h0 1567 | Event ReceiveProgress(bytesReceived As Int64, totalBytes As Int64, newData As Xojo.Core.MemoryBlock) 1568 | #tag EndHook 1569 | 1570 | #tag Hook, Flags = &h0, Description = 546865205245535466756C20736572766572206861732072657475726E6564206120726573706F6E73652E 1571 | Event ResponseReceived(url As Text, httpStatus As Integer, payload As Auto) 1572 | #tag EndHook 1573 | 1574 | #tag Hook, Flags = &h0 1575 | Event SendProgress(bytesSent As Int64, bytesLeft As Int64) 1576 | #tag EndHook 1577 | 1578 | #tag Hook, Flags = &h0, Description = 5365742075702070726F70657274696573206F722074616B65206F7468657220616374696F6E732061667465722074686520696E7374616E636520697320666972737420636F6E73747275637465642E 1579 | Event Setup() 1580 | #tag EndHook 1581 | 1582 | #tag Hook, Flags = &h0, Description = 52657475726E205472756520746F2070726576656E74206175746F6D617469632070726F63657373696E67206F662074686520696E636F6D696E67207061796C6F61642C206F72206368616E676520746865207061796C6F6164206265666F7265206175746F6D617469632070726F63657373696E672E 1583 | Event SkipIncomingPayloadProcessing(url As Text, httpStatus As Integer, ByRef payload As Auto) As Boolean 1584 | #tag EndHook 1585 | 1586 | 1587 | #tag Property, Flags = &h21 1588 | Private Shared ClassMetaDict As Xojo.Core.Dictionary 1589 | #tag EndProperty 1590 | 1591 | #tag Property, Flags = &h21 1592 | Private ClassName As Text 1593 | #tag EndProperty 1594 | 1595 | #tag Property, Flags = &h0 1596 | DefaultRESTType As RESTTypes = RESTTypes.Unknown 1597 | #tag EndProperty 1598 | 1599 | #tag Property, Flags = &h21 1600 | Private FlagGetRESTType As Boolean 1601 | #tag EndProperty 1602 | 1603 | #tag ComputedProperty, Flags = &h1 1604 | #tag Getter 1605 | Get 1606 | return RESTTypeToHTTPAction( RESTType ) 1607 | End Get 1608 | #tag EndGetter 1609 | Protected HTTPAction As Text 1610 | #tag EndComputedProperty 1611 | 1612 | #tag ComputedProperty, Flags = &h0 1613 | #tag Getter 1614 | Get 1615 | return mIsConnected 1616 | End Get 1617 | #tag EndGetter 1618 | IsConnected As Boolean 1619 | #tag EndComputedProperty 1620 | 1621 | #tag ComputedProperty, Flags = &h0 1622 | #tag Getter 1623 | Get 1624 | if mMessageOptions is nil then 1625 | MessageOptions = new M_REST.Options 1626 | end if 1627 | 1628 | return mMessageOptions 1629 | End Get 1630 | #tag EndGetter 1631 | #tag Setter 1632 | Set 1633 | if value = mMessageOptions then 1634 | // 1635 | // Nothing to do 1636 | // 1637 | return 1638 | end if 1639 | 1640 | if mMessageOptions isa Object then 1641 | // 1642 | // Clear the parent 1643 | // 1644 | PrivateOptions( mMessageOptions ).SetParentMessage nil 1645 | end if 1646 | 1647 | mMessageOptions = value 1648 | if mMessageOptions isa Object then 1649 | PrivateOptions( mMessageOptions ).SetParentMessage self 1650 | end if 1651 | 1652 | End Set 1653 | #tag EndSetter 1654 | MessageOptions As M_REST.Options 1655 | #tag EndComputedProperty 1656 | 1657 | #tag ComputedProperty, Flags = &h0 1658 | #tag Getter 1659 | Get 1660 | static nextSN as Int64 1661 | static accessFlag as new Semaphore( 1 ) 1662 | 1663 | if mMessageSerialNumber <= 0 then 1664 | accessFlag.Signal 1665 | 1666 | const kOne as Int64 = 1 1667 | nextSN = nextSN + kOne 1668 | mMessageSerialNumber = nextSN 1669 | 1670 | accessFlag.Release 1671 | end if 1672 | 1673 | return mMessageSerialNumber 1674 | 1675 | End Get 1676 | #tag EndGetter 1677 | MessageSerialNumber As Int64 1678 | #tag EndComputedProperty 1679 | 1680 | #tag ComputedProperty, Flags = &h21 1681 | #tag Getter 1682 | Get 1683 | if mMessageSurrogateWeakRef is nil then 1684 | return nil 1685 | else 1686 | return PrivateSurrogate( mMessageSurrogateWeakRef.Value ) 1687 | end if 1688 | 1689 | End Get 1690 | #tag EndGetter 1691 | #tag Setter 1692 | Set 1693 | if value is nil then 1694 | mMessageSurrogateWeakRef = nil 1695 | else 1696 | mMessageSurrogateWeakRef = Xojo.Core.WeakRef.Create( value ) 1697 | value.AppendMessage self 1698 | end if 1699 | 1700 | End Set 1701 | #tag EndSetter 1702 | Private MessageSurrogate As PrivateSurrogate 1703 | #tag EndComputedProperty 1704 | 1705 | #tag Property, Flags = &h0 1706 | MessageTag As Auto 1707 | #tag EndProperty 1708 | 1709 | #tag Property, Flags = &h21 1710 | Attributes( hidden ) Private mIsConnected As Boolean 1711 | #tag EndProperty 1712 | 1713 | #tag Property, Flags = &h21 1714 | Attributes( hidden ) Private mMessageOptions As M_REST.Options 1715 | #tag EndProperty 1716 | 1717 | #tag Property, Flags = &h21 1718 | Attributes( hidden ) Private mMessageSerialNumber As Int64 1719 | #tag EndProperty 1720 | 1721 | #tag Property, Flags = &h21 1722 | Private mMessageSurrogateWeakRef As Xojo.Core.WeakRef 1723 | #tag EndProperty 1724 | 1725 | #tag ComputedProperty, Flags = &h21 1726 | #tag Getter 1727 | Get 1728 | if ClassMetaDict is nil then 1729 | return nil 1730 | end if 1731 | 1732 | if ClassName = "" then 1733 | return nil 1734 | end if 1735 | 1736 | return ClassMetaDict.Value( ClassName ) 1737 | End Get 1738 | #tag EndGetter 1739 | Private MyMeta As M_REST.ClassMeta 1740 | #tag EndComputedProperty 1741 | 1742 | #tag Property, Flags = &h21 1743 | Private ReceiveFinishedMicroseconds As Double 1744 | #tag EndProperty 1745 | 1746 | #tag Property, Flags = &h21 1747 | Private RequestSentMicroseconds As Double = -1.0 1748 | #tag EndProperty 1749 | 1750 | #tag Property, Flags = &h21 1751 | Private RequestStartedMicroseconds As Double = -1.0 1752 | #tag EndProperty 1753 | 1754 | #tag Property, Flags = &h21 1755 | Private ResponseReceivedMicroseconds As Double = -1.0 1756 | #tag EndProperty 1757 | 1758 | #tag ComputedProperty, Flags = &h0 1759 | #tag Getter 1760 | Get 1761 | if FlagGetRESTType then 1762 | return DefaultRESTType 1763 | end if 1764 | 1765 | FlagGetRESTType = true 1766 | dim type as RESTTypes = RaiseEvent GetRESTType 1767 | if type = RESTTypes.Unknown then 1768 | type = DefaultRESTType 1769 | end if 1770 | FlagGetRESTType = false 1771 | 1772 | return type 1773 | End Get 1774 | #tag EndGetter 1775 | RESTType As RESTTypes 1776 | #tag EndComputedProperty 1777 | 1778 | #tag ComputedProperty, Flags = &h0 1779 | #tag Getter 1780 | Get 1781 | dim roundTrip as double 1782 | 1783 | if ResponseReceivedMicroseconds < 0.0 or RequestSentMicroseconds < 0.0 then 1784 | roundTrip = -1.0 1785 | else 1786 | roundTrip = ( ResponseReceivedMicroseconds - RequestSentMicroseconds ) / 1000.0 1787 | end if 1788 | 1789 | if roundTrip < 0.0 then 1790 | roundTrip = -1.0 1791 | end if 1792 | 1793 | return roundTrip 1794 | End Get 1795 | #tag EndGetter 1796 | RoundTripMs As Double 1797 | #tag EndComputedProperty 1798 | 1799 | #tag ComputedProperty, Flags = &h0 1800 | #tag Getter 1801 | Get 1802 | dim roundTrip as double 1803 | 1804 | if ReceiveFinishedMicroseconds < 0.0 or RequestStartedMicroseconds < 0.0 then 1805 | roundTrip = -1.0 1806 | else 1807 | roundTrip = ( ReceiveFinishedMicroseconds - RequestStartedMicroseconds ) / 1000.0 1808 | end if 1809 | 1810 | if roundTrip < 0.0 then 1811 | roundTrip = -1.0 1812 | end if 1813 | 1814 | return roundTrip 1815 | End Get 1816 | #tag EndGetter 1817 | RoundTripWithProcessingMs As Double 1818 | #tag EndComputedProperty 1819 | 1820 | #tag Property, Flags = &h21 1821 | Private TimeoutTimer As Xojo.Core.Timer 1822 | #tag EndProperty 1823 | 1824 | 1825 | #tag Constant, Name = kActionDelete, Type = Text, Dynamic = False, Default = \"DELETE", Scope = Protected 1826 | #tag EndConstant 1827 | 1828 | #tag Constant, Name = kActionGet, Type = Text, Dynamic = False, Default = \"GET", Scope = Protected 1829 | #tag EndConstant 1830 | 1831 | #tag Constant, Name = kActionOptions, Type = Text, Dynamic = False, Default = \"OPTIONS", Scope = Protected 1832 | #tag EndConstant 1833 | 1834 | #tag Constant, Name = kActionPatch, Type = Text, Dynamic = False, Default = \"PATCH", Scope = Protected 1835 | #tag EndConstant 1836 | 1837 | #tag Constant, Name = kActionPost, Type = Text, Dynamic = False, Default = \"POST", Scope = Protected 1838 | #tag EndConstant 1839 | 1840 | #tag Constant, Name = kActionPut, Type = Text, Dynamic = False, Default = \"PUT", Scope = Protected 1841 | #tag EndConstant 1842 | 1843 | #tag Constant, Name = kActionUnknown, Type = Text, Dynamic = False, Default = \"Unknown", Scope = Protected 1844 | #tag EndConstant 1845 | 1846 | #tag Constant, Name = kContentType, Type = Text, Dynamic = False, Default = \"application/json", Scope = Private 1847 | #tag EndConstant 1848 | 1849 | #tag Constant, Name = kVersion, Type = Text, Dynamic = False, Default = \"1.2", Scope = Public 1850 | #tag EndConstant 1851 | 1852 | 1853 | #tag Enum, Name = RESTTypes, Type = Integer, Flags = &h0 1854 | Unknown 1855 | Create 1856 | Read 1857 | UpdateReplace 1858 | UpdateModify 1859 | Authenticate 1860 | DELETE 1861 | GET 1862 | HEAD 1863 | OPTIONS 1864 | PATCH 1865 | POST 1866 | PUT 1867 | #tag EndEnum 1868 | 1869 | 1870 | #tag ViewBehavior 1871 | #tag ViewProperty 1872 | Name="DefaultRESTType" 1873 | Visible=true 1874 | Group="Behavior" 1875 | InitialValue="RESTTypes.Unknown" 1876 | Type="RESTTypes" 1877 | EditorType="Enum" 1878 | #tag EnumValues 1879 | "0 - Unknown" 1880 | "1 - Create" 1881 | "2 - Read" 1882 | "3 - UpdateReplace" 1883 | "4 - UpdateModify" 1884 | "5 - Authenticate" 1885 | "6 - DELETE" 1886 | "7 - GET" 1887 | "8 - HEAD" 1888 | "9 - OPTIONS" 1889 | "10 - PATCH" 1890 | "11 - POST" 1891 | "12 - PUT" 1892 | #tag EndEnumValues 1893 | #tag EndViewProperty 1894 | #tag ViewProperty 1895 | Name="Index" 1896 | Visible=true 1897 | Group="ID" 1898 | InitialValue="-2147483648" 1899 | Type="Integer" 1900 | #tag EndViewProperty 1901 | #tag ViewProperty 1902 | Name="IsConnected" 1903 | Group="Behavior" 1904 | Type="Boolean" 1905 | #tag EndViewProperty 1906 | #tag ViewProperty 1907 | Name="Left" 1908 | Visible=true 1909 | Group="Position" 1910 | InitialValue="0" 1911 | Type="Integer" 1912 | #tag EndViewProperty 1913 | #tag ViewProperty 1914 | Name="MessageSerialNumber" 1915 | Group="Behavior" 1916 | Type="Int64" 1917 | #tag EndViewProperty 1918 | #tag ViewProperty 1919 | Name="Name" 1920 | Visible=true 1921 | Group="ID" 1922 | Type="String" 1923 | #tag EndViewProperty 1924 | #tag ViewProperty 1925 | Name="RESTType" 1926 | Group="Behavior" 1927 | Type="RESTTypes" 1928 | EditorType="Enum" 1929 | #tag EnumValues 1930 | "0 - Unknown" 1931 | "1 - Create" 1932 | "2 - Read" 1933 | "3 - UpdateReplace" 1934 | "4 - UpdateModify" 1935 | "5 - Authenticate" 1936 | "6 - DELETE" 1937 | "7 - GET" 1938 | "8 - HEAD" 1939 | "9 - OPTIONS" 1940 | "10 - PATCH" 1941 | "11 - POST" 1942 | "12 - PUT" 1943 | #tag EndEnumValues 1944 | #tag EndViewProperty 1945 | #tag ViewProperty 1946 | Name="RoundTripMs" 1947 | Group="Behavior" 1948 | Type="Double" 1949 | #tag EndViewProperty 1950 | #tag ViewProperty 1951 | Name="RoundTripWithProcessingMs" 1952 | Group="Behavior" 1953 | Type="Double" 1954 | #tag EndViewProperty 1955 | #tag ViewProperty 1956 | Name="Super" 1957 | Visible=true 1958 | Group="ID" 1959 | Type="String" 1960 | #tag EndViewProperty 1961 | #tag ViewProperty 1962 | Name="Top" 1963 | Visible=true 1964 | Group="Position" 1965 | InitialValue="0" 1966 | Type="Integer" 1967 | #tag EndViewProperty 1968 | #tag ViewProperty 1969 | Name="ValidateCertificates" 1970 | Visible=true 1971 | Group="Behavior" 1972 | Type="Boolean" 1973 | #tag EndViewProperty 1974 | #tag EndViewBehavior 1975 | End Class 1976 | #tag EndClass 1977 | -------------------------------------------------------------------------------- /REST Resources/M_REST/TextProvider.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface 2 | Protected Interface TextProvider 3 | #tag Method, Flags = &h0 4 | Function ConvertToText() As Text 5 | 6 | End Function 7 | #tag EndMethod 8 | 9 | 10 | #tag ViewBehavior 11 | #tag ViewProperty 12 | Name="Index" 13 | Visible=true 14 | Group="ID" 15 | InitialValue="-2147483648" 16 | Type="Integer" 17 | #tag EndViewProperty 18 | #tag ViewProperty 19 | Name="Left" 20 | Visible=true 21 | Group="Position" 22 | InitialValue="0" 23 | Type="Integer" 24 | #tag EndViewProperty 25 | #tag ViewProperty 26 | Name="Name" 27 | Visible=true 28 | Group="ID" 29 | Type="String" 30 | #tag EndViewProperty 31 | #tag ViewProperty 32 | Name="Super" 33 | Visible=true 34 | Group="ID" 35 | Type="String" 36 | #tag EndViewProperty 37 | #tag ViewProperty 38 | Name="Top" 39 | Visible=true 40 | Group="Position" 41 | InitialValue="0" 42 | Type="Integer" 43 | #tag EndViewProperty 44 | #tag EndViewBehavior 45 | End Interface 46 | #tag EndInterface 47 | --------------------------------------------------------------------------------