Compare commits

...

699 Commits

Author SHA1 Message Date
fffa763d05 Updated a few comments. 2015-05-06 22:37:55 +02:00
d015c065f6 Updated readme. 2015-05-06 22:18:27 +02:00
8ea443c115 Added abstraction WSF_ROUTED, and WSF_FILTERED.
Added under library/server/obsolete/v0 the previous non concurrent friendly version of EWF/WSF, for backward compatiblity.
Removed WSF_CALLBACK_SERVICE and WSF_TO_WGI_SERVICE which are not need with new EWF.
2015-05-06 22:17:37 +02:00
019393fdb1 Fixed typo. 2015-05-06 22:17:35 +02:00
da8028f8b3 Fixed a typo. 2015-05-06 22:17:33 +02:00
20ed000879 Added a few descriptions and comments. 2015-05-06 22:16:57 +02:00
jvelilla
24620b228c Added feature comments.
Added missing postconditions.
2015-05-06 22:16:10 +02:00
jvelilla
9c7e29b836 Added descriptions and comments 2015-05-06 22:16:08 +02:00
jvelilla
a0e9a41e21 Added descriptions and feature comments. 2015-05-06 22:16:07 +02:00
jvelilla
dd9aff03d3 Added features comments. 2015-05-06 22:16:05 +02:00
jvelilla
dc35925eb0 Added Missing Class and feature descriptions.
Removed author entry.
2015-05-06 22:16:03 +02:00
a1a620a9c3 Export request and response from WGI_EXECUTION to itself.
Added WSF_FILTERED_ROUTED_SKELETON_EXECUTION
2015-05-06 22:16:00 +02:00
d8ea9ba63c renamed keep_alive_requested as is_persistent_connection_requested. 2015-05-06 22:15:59 +02:00
c42af5b2de Following the spec, use "keep-alive" and "close" in lowercase for Connection header. 2015-05-06 22:15:57 +02:00
d9cbc72058 Better support for HTTP/1.0 and also related to persistent connection. 2015-05-06 22:15:56 +02:00
7e057b20b1 Improved support for HTTP/1.0 persistent connection. 2015-05-06 22:15:54 +02:00
3165c1e5c6 Enable support for persistent connections.
(test: works fine with curl -k , but weird behavior with ab -k ...)
2015-05-06 22:15:53 +02:00
89e26519e4 First step to improve a bit error handling related to socket disconnection.
Mainly in standalone connector for now.
2015-05-06 22:15:51 +02:00
9d20e85c03 Improved the simple_file example with image, and not found message.
Use standalone connector in SCOOP concurrency mode.
2015-05-06 22:15:50 +02:00
48cb99498c Cleaned simple example, and made the standalone target with SCOOP concurrency. 2015-05-06 22:15:48 +02:00
8246bc1444 Updated various indexing notes.
Removed a few obsolete classes.
Cosmetics
2015-05-06 22:15:46 +02:00
9e1083eba8 Added migration note. 2015-05-06 22:15:44 +02:00
4907bc3085 Migrated most of the example and library to new design. 2015-05-06 22:15:43 +02:00
7d2ce8a77f Implemented support for base url in httpd connector. 2015-05-06 22:15:38 +02:00
b4a9c92ffc Migrated simple, simple_file and upload_image example.
Adapted EWF accordingly.
2015-05-06 22:14:48 +02:00
bf0eb9a02d Added SCOOP support for WSF.
WSF_SERVICE is deeply changed, and addition of WSF_EXECUTION.
Todo: code cleaning, removing useless things.
2015-05-06 22:13:22 +02:00
ddf73077b3 Support for concurrencies: none, thread and SCOOP 2015-05-06 22:13:19 +02:00
3da80fce0d Finally SCOOP supported. 2015-05-06 22:13:17 +02:00
0970de5dc6 Experiment to avoid pseudo sequential execution 2015-05-06 22:13:15 +02:00
557b11f4e6 First attempt to use `{NETWORK_STREAM_SOCKET}.accept_to' 2015-05-06 22:13:13 +02:00
7f27a6c797 First steps to provide a concurrent compliant EWF connector. 2015-05-06 22:13:11 +02:00
c778e454cd Renamed a few index.md as README.md 2015-05-05 11:13:12 +02:00
44757b73eb Renamed Home.md as README.md 2015-05-05 11:10:36 +02:00
525978db1d Update doc structure, and fixed a few links. 2015-05-05 10:57:58 +02:00
71c90a2f39 Updated mediawiki and markdown link to local pages,
in order to use those files as browseable documentation, and close the github wiki.
2015-05-05 10:22:21 +02:00
8057dca032 Merge remote-tracking branch 'ewf_wiki/master' 2015-05-05 10:06:12 +02:00
91d7b956b9 update README to add google groups info. 2015-05-05 09:58:36 +02:00
881625a0f6 Updated code to remove obsolete call on recent version of json library.
Updated upload_image example to use PATH instead of DIRECTORY_NAME or similar.
Removed unused local variables.
2015-04-07 19:27:30 +02:00
b7a12eddaf Merge branch 'master' of https://github.com/eiffelhub/json 2015-04-07 18:36:38 +02:00
jvelilla
44b1ccbc3c Merge branch 'jvelilla-ewf_cookie' 2015-03-20 09:35:51 -03:00
jvelilla
30261632f6 Updated HTTP_COOKIE, enable to add a cookie with empty value.
Added feature to check if a date is valid rcf1123 is_valid_rfc1123_date.
Added test cases related to valid cookie dates.
Updated wsf_response add_cookie basedo on review comments.
2015-03-19 15:23:06 -03:00
jvelilla
08db0748f4 Updated is_valid_character, using NATURAL_32 as an argument to avoid multiple conversions.
Updated add_cookie, added features has_cookie_name and is_cookie line to avoid the use of
STRING.split and STRING.start_with.
2015-03-19 09:39:41 -03:00
jvelilla
9dc22bee24 Updated HTTP_COOKIE class based on comments.
Added missing descriptions in test classes
2015-03-17 17:00:07 -03:00
jvelilla
c4d362ff31 Added the add_cookie feature
Added test cases to check cookies in WSF_RESPONSE-
Added mock classes use for test cases.
2015-03-17 14:27:53 -03:00
jvelilla
4a35ff7b77 Updated code based on Jocelyn's comments. 2015-03-13 17:41:48 -03:00
jvelilla
871e9792a5 Added HTTP_COOKIE and test cases.
Added WSF_COOKIE class, inherit from HTTP_COOKIE.
2015-03-13 15:28:38 -03:00
5f4ab50bf9 Completed configuration setting to be compilable with recent changes in EiffelNet / NETWORK_STREAM_SOCKET interface. 2015-03-12 22:16:28 +01:00
f0a49aaf0a fixed location of before_15_01 folder. 2015-03-11 14:52:14 +01:00
1aae58e00b Removed the -safe since now new project should be void-safe 2015-03-05 20:37:28 +01:00
f81e5251e8 moved wizard under tools/estudio_wizard 2015-03-05 16:01:45 +01:00
b26504b4a1 moved wizard from tools to helpers 2015-03-05 16:00:43 +01:00
4eddad0bcb Updated script to install wizard in current EiffelStudio installation. 2015-03-05 15:27:29 +01:00
1b9aa0c598 Updated the ewf estudio wizard to have a console and a graphical wizard.
Usage:  wizard -callback file.cb path-to-rootdir folder.
2015-03-05 15:23:13 +01:00
6e52774507 Prepare nino ecf to be compilable with upcoming changes in EiffelNet / NETWORK_STREAM_SOCKET interface.
As EiffelNet release is related to EiffelStudio release,
   the condition "compiler version <= 15.02) is used,
   which means that before for release 15.01 and previous EiffelStudio
   releases, the project uses a specific TCP_STREAM_SOCKET, and for
   upcoming releases, it will use another version of that class).
  (see rev#96640 from eiffelstudio subversion repository)
2015-02-18 10:14:08 +01:00
e5403462bc Prepare nino ecf to be compilable with upcoming changes in EiffelNet / NETWORK_STREAM_SOCKET interface.
(see rev#96640 from eiffelstudio subversion repository)
2015-02-18 10:08:36 +01:00
33b555ff27 Fixed implementation of JSON_PARSER.is_valid_number (STRING): BOOLEAN 2015-01-08 18:57:31 +01:00
4c552671c1 Updated install_ewf.bat to use the new "ecf_tool" from https://svn.eiffel.com/eiffelstudio/trunk/Src/tools/ecf_tool . 2014-12-02 10:51:08 +01:00
25a362d043 Added more test cases for cookies. 2014-12-02 10:50:29 +01:00
023e03bb8f Completed change on debug handler and filter, to use WSF_DEBUG_INFORMATION. 2014-12-02 10:45:33 +01:00
0caad2105f Merge branch 'fix_cgi_value' of github.com:jocelyn/EWF 2014-12-01 15:53:45 +01:00
f14fdc2a69 Added assertions on router helpers, and also agent handler.
Closes issue #159
2014-12-01 15:44:49 +01:00
440d3f9c91 Fixing issues related to status code. 2014-11-28 16:10:50 +01:00
975ef90bab Better code for restbucks ORDER_HANDLER related to allowed_cross_origins and last_modified. 2014-11-28 16:06:30 +01:00
8c63e74b81 Fixed compilation of restbucks example using the policy driven framework. 2014-11-25 22:19:46 +01:00
6b9d248542 WSF_TRACE_RESPONSE should include "Content-Type: message/http" header
Close issue #145
2014-11-25 15:55:48 +01:00
6d2318ac9b Fixed issue#157 (WSF_REQUEST.cookies_table does not terminate on cookies without a value, or ending with semi-colon)
Added related autotest.
2014-11-24 22:22:12 +01:00
Colin Adams
0f76518b63 Added {WSF_REQUEST}.http_content_encoding 2014-11-19 14:41:50 +00:00
Colin Adams
bb5faec3c6 Issue #154 (documentation error in {WSF_SKELETON_HANDLER}.check_request) 2014-11-19 10:35:06 +00:00
Colin Adams
22301fc15d issue #149 (Simple CORS support for GET requests in policy-driven framework) 2014-11-18 16:02:10 +00:00
Colin Adams
f482ef06d5 Issue #150 (VARY header set to header contents rather than heqader name) 2014-11-18 13:48:38 +00:00
Colin Adams
4f62da8f90 Issue #144 (Add last_modified to WSF_SKELETON_HANDLER) 2014-11-18 10:37:36 +00:00
Jocelyn Fiat
eaa3dd435a Merge pull request #148 from colin-adams/response-code-411
Policy-driven framework should reject PUT requests that contain a Content-Range header

Close Issue #143
2014-11-17 17:37:06 +01:00
Colin Adams
e1d1d52260 Issue #143 2014-11-17 16:20:28 +00:00
0cc0ba047f Reintroduced parse_object as obsolete, to avoid breaking existing code. 2014-11-17 16:05:33 +01:00
641e114fed Converted ecf file to complete void-safe.
Improved JSON_PRETTY_STRING_VISITOR to support STRING_8 or STRING_32 output.
Added examples.
Added doc in the folder "doc".
Updated Readme and other files.
Added package.iron file.
2014-11-17 11:22:33 +01:00
73d45c9817 Updated WSF_FILE_UTILITIES with class comment,
and avoid having expanded generic class.
2014-10-28 12:52:23 +01:00
519b959073 Fixed compilation issue for wsf_js_widget package. 2014-10-10 16:06:03 +02:00
2cc751f326 Fixed compilation for wsf tests. 2014-10-10 14:26:50 +02:00
99588faf40 fixed compilation of filter example. 2014-10-10 13:51:20 +02:00
Jocelyn Fiat
9c6b6b978a Merge pull request #11 from jocelyn/improved_sept_2014
Fixed various issue with parsing string (such as \t and related),
    Implemented escaping of slash '/' only in case of '</' to avoid potential issue with javascript and </script>
    Many feature renaming to match Eiffel style and naming convention, kept previous feature as obsolete.
    Restructured the library to make easy extraction of "converter" classes if needed in the future.
    Marked converters classes as obsolete.
    Updated part of the code to use new feature names.
    Updated license and copyright.
    Updated classes with bottom indexing notes related to copyright and license.
2014-10-03 18:46:00 +02:00
0647a74875 Ensure backward compatibility for parse' / is_parsed'. 2014-10-03 18:44:09 +02:00
Jocelyn Fiat
de9d99e6bc Merge pull request #140 from jvelilla/ewf_router
Updated WSF_ROUTER, to import an existing router definition.
2014-10-01 19:41:38 +02:00
ae9f67391c Marked converters classes as obsolete. 2014-09-30 10:46:28 +02:00
82f832a556 Updated license and copyright.
Updated classes with bottom indexing notes related to copyright and license.
2014-09-30 10:46:12 +02:00
19dbbf89e7 Fixed various issue with parsing string (such as \t and related),
Implemented escaping of slash '/' only in case of '</' to avoid potential issue with javascript and </script>
Many feature renaming to match Eiffel style and naming convention, kept previous feature as obsolete.
Restructured the library to make easy extraction of "converter" classes if needed in the future.
Updated part of the code to use new feature names.
2014-09-24 20:08:12 +02:00
Olivier Ligot
5d6e3c69ee Fix filter example: logging filter must be the last one 2014-09-18 13:29:24 +02:00
Olivier Ligot
984d04e972 Filter example: add fcgi target 2014-09-17 17:11:37 +02:00
Olivier Ligot
83486ae0cc Fix authentication filter: use {HTTP_AUTHORIZATION}.is_basic 2014-09-17 15:40:43 +02:00
jvelilla
4fe5c5da7e Updated WSF_ROUTER.import feature. 2014-09-12 10:54:22 -03:00
jvelilla
ec1d8ca52f Updated WSF_ROUTER, to import an existing router definition. 2014-09-10 12:57:34 -03:00
Olivier Ligot
0404627153 Merge remote-tracking branch 'upstream/master' 2014-07-11 15:00:20 +02:00
jvelilla
de282948e6 Merge pull request #9 from Conaclos/working
Apply pretty tool.
2014-07-08 17:25:35 +02:00
Jocelyn Fiat
93f1fed997 Merge pull request #139 from jocelyn/widget_integration
Added custom-template in examples, as a base template to integrate easily other JS widgets.
2014-07-07 12:30:10 +02:00
f6ebd414d6 Added custom-template in examples, as a base template to integrate easily other JS widgets.
Added custom example (based on custom-template project) that demonstrates how to integrate a thirdparty JS component such as d3 within the application using wsf_js_widget.

Removed various unecessary ecf dependencies.
2014-07-07 12:15:18 +02:00
ff19adc6c8 Improved comment related to PATH_INFO and stripping multiple slashes sequence to single slash. 2014-07-07 11:27:31 +02:00
Jocelyn Fiat
41d24c91b4 Merge pull request #138 from jocelyn/widget_integration
Integrated WSF_JS_Widget library provided by Yassin Nasir Hassan and Severin Munger as an ETH student project.
It was updated to better support Unicode, and other minor changes, this is still under "draft" folder, as it may need various modifications on the interface and implementation.
2014-07-07 11:19:43 +02:00
0427f7a8d3 Fixed compilation issue related to old usage of modified JSON library. 2014-07-07 11:14:36 +02:00
985a5e5ce7 Merge branch 'master' of github.com:EiffelWebFramework/EWF into widget_integration 2014-07-07 10:30:42 +02:00
fe4c283336 Move wsf_js_widget library under draft/library/server/wsf_js_widget 2014-07-07 10:26:10 +02:00
Conaclos
20e704604a Apply pretty print tool.
Apply on each class in test suite and library.
2014-07-04 17:59:05 +02:00
jvelilla
0db02a8c52 Merge pull request #8 from Conaclos/working
Tests - Update syntax and improve implementation
2014-07-04 14:07:41 +02:00
1b4b50ee80 Replace any multiple slash sequence by a single slash character for PATH_INFO. 2014-07-02 11:36:43 +02:00
446c692f97 Various changes related to new WSF_DEBUG_INFORMATION and WSF_DEBUG_HANDLER. 2014-07-01 19:59:08 +02:00
7dfc6ea67a Fixed various issues related to unicode and CGI variables (assuming that CGI variables are utf-8 encoded, and sometime percent encoded).
Delayed computation of `value' and `name' from WSF_STRING.
Fixed computation of REQUEST_URI when the server does not provide it (this is rare, but possible).
   compute it as SERVER_NAME + encoded-PATH_INFO + {? + QUERY_STRING}
2014-07-01 19:57:14 +02:00
jvelilla
a5a257f452 Update format 2014-07-01 04:47:23 -07:00
jvelilla
bde0e2900b Created Deployment (markdown) 2014-07-01 04:42:56 -07:00
Conaclos
361773101e Add documentation and contracts for domain types. 2014-06-30 18:32:14 +02:00
Conaclos
052860b62c Improve converters.
Replace old syntax with new one and improve
implementation.
2014-06-30 18:31:42 +02:00
Conaclos
c5e1b1ee69 Syntax update.
Replace assigment attempt with object test.
2014-06-30 18:28:13 +02:00
0b1697f20d Verbose mode for the WSF_DEBUG_HANDLER. 2014-06-30 15:45:54 +02:00
add71543a4 Fixed error introduced during refactorying on WSF_DEBUG_FILTER 2014-06-30 15:21:03 +02:00
66a1e0629c Improved the debug example, so that it outputs more information. 2014-06-30 15:16:31 +02:00
425c976032 Ensure that PATH_INFO and REQUEST_URI are following the CGI specifications:
- PATH_INFO is percent decoded but still utf-8 encoded,
  this is available via WGI.path_info and WSF_REQUEST.utf_8_path_info.
- Added WSF_REQUEST.percent_encoded_path_info
- and WSF_REQUEST.path_info remains the unicode value for PATH_INFO

Added cgi_variables: WGI_REQUEST_CGI_VARIABLES to have a simple and quick view on CGI variables
Added execution_variables to be able to iterate on execution variables.
Added PERCENT_ENCODER.percent_decoded_utf_8_string
Improved the WSF_DEBUG_HANDLER to provide more information thanks to WSF_DEBUG_INFORMATION object.
2014-06-30 15:13:47 +02:00
Jocelyn Fiat
397dcc6128 Merge pull request #133 from jocelyn/better_uploading_file
Improved the uploading of file in regard to temporary filename.
2014-06-23 16:06:29 +02:00
a3c403323d Raised the void-safety level to "complete"
Added comments.
2014-06-23 16:05:20 +02:00
942896aa0c Fixed library location for http 2014-06-12 20:02:57 +02:00
93c92c0e38 Avoid decoding PATH_INFO and PATH_TRANSLATED to follow CGI spec. 2014-06-12 19:54:30 +02:00
394ca46f03 Added example to help debugging EWF
This is mainly a kind of echo server .. that return the request information.
2014-06-12 19:52:41 +02:00
67641da44d Improved the uploading of file in regard to temporary filename.
Avoid to overwrite the same file for concurrent requests uploading the same filename.
2014-06-11 16:52:22 +02:00
Olivier Ligot
a826051979 Merge remote-tracking branch 'upstream/master' 2014-05-22 22:09:00 +02:00
Jocelyn Fiat
ce4c62a989 Merge pull request #131 from jocelyn/void-safe
Make sure to be able to compile in complete void-safe for 14.05 and still compile with 13.11
2014-05-14 16:21:21 +02:00
b59966595e Make sure to be able to compile in complete void-safe for 14.05 and still compile with 13.11 2014-05-14 16:18:10 +02:00
fcf8b63666 Make sure to be able to compile in complete void-safe for 14.05 and still compile with 13.11 2014-05-14 16:16:32 +02:00
cad9322839 Merge branch 'master' into void-safe 2014-05-14 11:32:28 +02:00
31fcd61401 Make sure to be able to compile in complete void-safe for 14.05 and still compile with 13.11 2014-05-14 10:14:51 +02:00
Jocelyn Fiat
0b11663da4 Merge pull request #128 from jocelyn/response_header
Extracting HTTP_HEADER_BUILDER from HTTP_HEADER
Improving wsf session usage
Various unicode related improvement for router and error library.
2014-05-14 10:06:58 +02:00
5a179f514c Minor change to avoid unecessary conversion from eventual immutable string 8 to string 8. 2014-05-14 10:04:17 +02:00
f099a70b87 Apply recent change on error_handler interface to support unicode error message in response. 2014-05-14 10:03:15 +02:00
1163b99f39 Support for unicode error message for the ERROR_HANDLER.as_string_representation: STRING_32
and as well for debug_output, this avoid unecessary unicode string truncation.
2014-05-14 10:02:38 +02:00
ca6ccc7291 debug_output can return a string 32, so avoid truncated unicode value by returning a string 32 value for `debug_output' . 2014-05-14 09:59:29 +02:00
bb11c24681 check that cookies data is valid string 8 to follow assertions. 2014-05-14 09:53:04 +02:00
d158579bdc Replaced notion of session uuid by session id which is more generic (could be a uuid, or something else).
Use STRING_TABLE for the implementation of session data container.
Added a few missing comments.
2014-05-14 09:45:15 +02:00
02f5a09689 Added comment to explain why conversion to string 8 is safe 2014-05-14 09:36:22 +02:00
cb3de17be9 renamed HTTP_HEADER_BUILDER as HTTP_HEADER_MODIFIER 2014-05-14 09:35:55 +02:00
fd66d79ecb Updated ecf files toward complete void-safety
Added iron package files.
Added libfcgi files to compile .lib and .dll on Windows
2014-04-22 21:47:29 +02:00
d6b77e938b Added more tests for uri-template matching, especially with url that contains %2F i.e the percent encoded slash '/' 2014-04-22 19:25:07 +02:00
3c8dc0a9e1 Fixed various Unicode text handling.
Moved example folder inside the library, and renamed it "demo"
Improved example code.
2014-04-22 16:36:29 +02:00
fdfeea508e Merge branch 'master' of https://github.com/EiffelWebFramework/EWF.wiki 2014-04-22 15:50:44 +02:00
99d0340e1b Merge branch 'master' of https://github.com/eiffelhub/json 2014-04-22 15:50:30 +02:00
a74cda2f33 Added support for UTF-8 during decoding.
The JSON specification does not require it, but some json encoders are using utf-8 encoding for json encoding.
Added related autotest case.
2014-04-22 15:45:31 +02:00
322fd80f40 Be sure to reset `is_https' to False, in case the wsf_request object is reused by the implementation. 2014-04-22 10:18:16 +02:00
7168941495 is_https should not rely on REQUEST_SCHEME which may still be "http" for SSL connection. 2014-04-22 10:09:03 +02:00
161607cf8a better comments. 2014-04-22 10:01:27 +02:00
d45cd032a7 Corrected support of https request in `server_url' (and callers).
Added query `is_https' to indicate if the request is done via a https connection or not.
2014-04-22 09:59:18 +02:00
Jocelyn Fiat
9db9a4957a Updated Documentation__Request (markdown) 2014-04-17 07:24:13 -07:00
Jocelyn Fiat
d089921ef5 Updated Documentation__Request (markdown) 2014-04-17 07:23:54 -07:00
Jocelyn Fiat
7f3ece2da9 Updated Documentation__Request (markdown) 2014-04-17 07:23:33 -07:00
4b497060a0 Added an example to embed EWF nino service into a Vision2 desktop application.
This is locally consumed via the embedded web browser component.
2014-04-10 15:28:19 +02:00
d40131f863 Updated encoder library, especially URL encoders to reuse implementation of percent_encoder.e
Fixed JSON_ENCODER for %T and related.
Updated related autotest cases.
2014-04-09 18:10:51 +02:00
9999b5e400 Moved implementation of WSF_PERCENT_ENCODER into "encoder" library, and added the *partial* variant. 2014-04-09 17:19:09 +02:00
6e27f66306 Improved BASE64 to update has_error when decoding.
Added manual tests.
2014-04-09 16:56:40 +02:00
a4c1263190 fixed code for test_url_encoder 2014-04-09 16:22:42 +02:00
46920fb991 Do not try to read more bytes from input than provided Content-Length value. 2014-04-09 12:27:31 +02:00
d50b3cb28c For maintenance filter, response with http status code {HTTP_STATUS_CODE}.service_unavailable 2014-04-09 12:22:36 +02:00
6481d2ec7d Fixed all-stable-safe.ecf fusion 2014-04-09 12:22:25 +02:00
f94820c824 Fixing JSON encoding code to include among other TAB (%T <-> \t) 2014-04-09 08:34:43 +02:00
1d0a2363d8 Fixed issue with URL_ENCODER encoding (and small optimization) 2014-04-08 21:52:37 +02:00
Jocelyn Fiat
2100b856b0 Updated Documentation__Request (markdown) 2014-04-02 01:52:31 -07:00
Jocelyn Fiat
e687affd17 Updated Documentation__Request (markdown) 2014-04-02 01:52:00 -07:00
Jocelyn Fiat
195f3b4f68 Updated Documentation__Request (markdown) 2014-04-02 01:51:04 -07:00
cc7d268610 Code improvement
Cosmetic (comments, names, formatting)
2014-03-26 10:18:02 +01:00
hassany
acc8cda04f Fix STRING_32 issues 2014-03-19 23:13:16 +01:00
hassany
7c5637c063 Add javascript function 2014-03-19 21:37:07 +01:00
severin
b87392906b Updated readme 2014-03-19 16:58:08 +01:00
severin
4e7e1e9c45 Added more comments and assertions to all classes; clean up 2014-03-19 16:49:24 +01:00
da92d2d365 Added alias "[]" to `item', to get header value for a header name.
Added assigner for `item' to make it easier to add header item without confusing key and value.
Better parameter names (more explicit)
2014-03-18 14:13:16 +01:00
ae0ba66416 Added comments, used better parameter names. 2014-03-17 21:30:34 +01:00
718cebc700 Extracting HTTP_HEADER_BUILDER from HTTP_HEADER
to provide useful interface on WSF_RESPONSE,
  and make WSF_SESSION easier to use.
2014-03-17 18:10:55 +01:00
a2cbcbbbc6 Updated demo_basic example to be easier to read, and demonstrate various scenario. 2014-03-13 13:06:57 +01:00
hassany
c5363c948c Extend documentation 2014-03-12 21:51:15 +01:00
severin
4f7086a6de Updated comments and added contracts for core controls in webcontrol 2014-03-12 17:21:39 +01:00
severin
3c4e15b386 Merge branch 'widget' of github.com:ynh/EWF into widget 2014-03-12 13:54:45 +01:00
hassany
6685b3679b Add file definition 2014-03-12 13:54:20 +01:00
severin
d6a27c26aa Added assets to library 2014-03-05 15:58:10 +01:00
severin
e7c4b949f5 Merge branch 'widget' of github.com:ynh/EWF into widget 2014-03-05 15:57:24 +01:00
severin
f89e0abe69 Simplified WSF_EMAIL_VALIDATOR regexp 2014-03-05 15:57:16 +01:00
YNH Webdev
cbcf9550f8 Rename WSF_FILE to WSF_FILE_DEFINITION 2014-03-05 15:07:21 +01:00
YNH Webdev
d4b877f18e Add Basepath 2014-03-05 15:05:26 +01:00
YNH Webdev
605a094910 Change STRING TO STRING_32 2014-03-05 14:54:45 +01:00
Jocelyn Fiat
a16a7358d1 Update README.md 2014-03-03 17:59:26 +01:00
Olivier Ligot
655c95158f json: comment '* text=auto' in .gitattributes 2014-03-03 14:18:07 +01:00
9eca723dc5 Added a demo application server for basic http autorization 2014-03-03 12:45:41 +01:00
bbc2bab0eb Removed usage of remote anchor types. 2014-02-28 14:25:13 +01:00
Jocelyn Fiat
fe913b0072 added anchor link for wiki and jekyl engine 2014-02-27 06:48:24 -08:00
Jocelyn Fiat
9ec2baf7d3 used <a name=".."></a> instead of <a name=".."/> form (jekill has trouble with it) 2014-02-27 06:39:28 -08:00
cc6d2f3023 Merge branch 'master' of https://github.com/eiffelhub/json 2014-02-27 09:16:48 +01:00
2ac717592d Merge branch 'master' of https://github.com/EiffelWebFramework/EWF.wiki 2014-02-27 09:16:19 +01:00
YNH Webdev
7ca62463b7 Rename progress_source 2014-02-26 10:55:33 +01:00
95971618ca Fixed autotests cases compilation of http_authorization library. 2014-02-24 22:07:24 +01:00
cb881877ac Fixed the ecf to test global compilation of EWF. 2014-02-24 21:56:23 +01:00
YNH Webdev
2cc26f98c6 Add class description to validators
Rename Wsf_progresssource
2014-02-23 19:10:23 +01:00
YNH Webdev
47b4357a72 Extend upload demo 2014-02-23 13:36:55 +01:00
YNH Webdev
a60bd19e58 Fix state transition 2014-02-23 13:14:09 +01:00
severin
439e43fad9 Began with class documentation 2014-02-21 00:23:35 +01:00
colin-adams
7abbc96347 Removed warning about not being part of release. 2014-02-11 00:39:03 -08:00
Jocelyn Fiat
e9b4a8abd5 Updated Home (markdown) 2014-02-03 09:38:20 -08:00
cb7c20a0b7 Udated to highest level of void-safety.
Fixed obsolete calls.
2014-02-03 09:52:09 +01:00
f5c2f9e017 Updated README.md 2014-01-27 10:10:41 +01:00
YNH Webdev
45ddc47b0e Finalize WSF_DYNAMIC_MULTI_CONTROL 2014-01-26 22:07:15 +01:00
YNH Webdev
8f148f2a5e Add dynamic multicontrol 2014-01-26 15:02:06 +01:00
YNH Webdev
5c9edeeae8 Image preview 2014-01-25 23:43:18 +01:00
YNH Webdev
13349d07a8 Fix upload state 2014-01-25 18:00:31 +01:00
991389e9b9 Update restbucksCRUD example to use "crypto" library rather than "eel".
Updated readme.md to add curl command to test the server.
2014-01-24 11:06:01 +01:00
d8487e6c12 Added PUT processing for image_uploader EWF example. 2014-01-24 11:06:00 +01:00
jvelilla
b7750b9d06 Udated to highest level of void-safety.
Fixed obsolete calls.
2014-01-12 16:56:16 -03:00
severin
d82cacc18f Merge branch 'widget' of github.com:ynh/EWF into widget 2014-01-11 12:53:59 +01:00
YNH Webdev
564248284a Add set value to value controls 2014-01-11 01:10:24 +01:00
severin
ee473d8844 Included time library to set current date in date picker 2014-01-11 00:19:04 +01:00
severin
2fb0d73439 Added ability to form element to get value (for convenience/completion) 2014-01-10 15:32:05 +01:00
severin
5dd8a83081 Added ability to show/hide border of form elements 2014-01-08 22:12:02 +01:00
severin
f83a8db25c Small change on date picker control, removed date input 2014-01-08 20:29:09 +01:00
jvelilla
a3e5da052e Merge pull request #127 from jvelilla/master
Fixed error with identity encoding.
2014-01-07 10:21:05 -08:00
jvelilla
942db6d708 Fixed error with identity encoding. 2014-01-07 15:09:54 -03:00
Jocelyn Fiat
48deb869de Created Documentation__Connector (markdown) 2014-01-07 05:12:09 -08:00
Jocelyn Fiat
69b67b3b4b Updated Documentation (markdown) 2014-01-07 05:11:40 -08:00
Jocelyn Fiat
6acdcb4e6d Created Documentation__Router (markdown) 2014-01-07 05:10:44 -08:00
Jocelyn Fiat
e832478b76 Updated Documentation _Router (markdown) 2014-01-07 05:10:23 -08:00
Jocelyn Fiat
c8e9a835f5 Created Documentation__Response (markdown) 2014-01-07 05:10:14 -08:00
Jocelyn Fiat
06c5f068db Created Documentation__Request (markdown) 2014-01-07 05:10:04 -08:00
Jocelyn Fiat
b81207e42e Created Documentation _Router (markdown) 2014-01-07 05:09:21 -08:00
Jocelyn Fiat
b312d69afa Updated Documentation (markdown) 2014-01-07 05:08:47 -08:00
Jocelyn Fiat
d1238a441d Created Documentation__Service (markdown) 2014-01-07 05:06:13 -08:00
Jocelyn Fiat
580739d0b4 Updated Home (markdown) 2014-01-07 04:52:59 -08:00
Jocelyn Fiat
093dec1808 Updated Documentation (markdown) 2014-01-07 04:22:11 -08:00
Jocelyn Fiat
2fb521aa42 Updated Documentation (markdown) 2014-01-07 03:37:03 -08:00
Jocelyn Fiat
992504a49f Updated Documentation (markdown) 2014-01-07 03:33:37 -08:00
Jocelyn Fiat
8696681710 Updated Documentation (markdown) 2014-01-07 03:28:25 -08:00
Jocelyn Fiat
73ce700ece Updated Documentation (markdown) 2014-01-07 03:17:44 -08:00
Jocelyn Fiat
c766881052 Updated Documentation (markdown) 2014-01-07 03:17:15 -08:00
Jocelyn Fiat
8bd14f5f21 Updated Documentation (markdown) 2014-01-07 03:13:06 -08:00
Jocelyn Fiat
45cd633e12 Updated Documentation (markdown) 2014-01-07 03:10:50 -08:00
Jocelyn Fiat
0744e13132 draft 2014-01-07 03:04:19 -08:00
severin
320584a693 Modified datepicker control 2014-01-06 01:36:32 +01:00
severin
514a44e022 Removed country chooser widget 2014-01-05 15:01:14 +01:00
severin
191a00649f fixed js 2014-01-05 02:00:46 +01:00
severin
ecfd5738ce modified country and date/time chooser 2014-01-05 01:26:11 +01:00
severin
25fe7c8725 Included bootstrap datetimepicker 2014-01-04 16:33:08 +01:00
severin
dbcb1def29 Added date chooser widget 2014-01-04 16:14:30 +01:00
severin
c4acbf563f Added precondition in layout control 2014-01-04 14:15:05 +01:00
severin
c9599f449f Removed add_dropdown methods from navbar, some cleanup in different controls 2014-01-04 13:43:51 +01:00
severin
e675e8aad9 ATTENTION: ugly append_attributes added to stateless control, replaces set_attributes -> maybe improve 2014-01-04 10:51:07 +01:00
severin
37aac7053a Moved set_attributes from BASIC_CONTROL to STATELESS_CONTROL 2014-01-04 10:30:34 +01:00
severin
9c9a132329 Merge branch 'widget' of github.com:ynh/EWF into widget 2014-01-03 12:06:53 +01:00
YNH Webdev
ce305d4e54 Add disable option 2014-01-02 18:19:59 +01:00
YNH Webdev
d3c66cd7fe Allow remove 2014-01-02 03:20:57 +01:00
YNH Webdev
7bf95cd927 Add serverside file id to file structure 2014-01-01 23:50:12 +01:00
YNH Webdev
05d4f24f6f Allow detached values 2014-01-01 23:48:56 +01:00
YNH Webdev
d9c837918b Demo upload 2014-01-01 20:41:28 +01:00
severin
5adee83350 Merge branch 'widget' of github.com:ynh/EWF into widget 2014-01-01 14:44:30 +01:00
severin
720e26d19d Small page control change 2014-01-01 14:44:22 +01:00
YNH Webdev
29356c0b61 Workin file upload 2014-01-01 01:35:43 +01:00
YNH Webdev
b39dd5c40d Change parameter type 2013-12-31 21:25:01 +01:00
YNH Webdev
1ae44e74e7 File upload implementation part1 2013-12-31 16:03:24 +01:00
YNH Webdev
7a5d1e378d Fix dropdown list, clean up actions 2013-12-31 12:10:05 +01:00
c68f6a30e6 Fixed and improved {WSF_REQUEST}.read_input_data_into_file.
Now use the content length to get exactly what is expected from the request.
Added check assertion
2013-12-03 10:46:22 +01:00
07ec0d001f Fixed various issues with libfcgi on Linux, mainly related to stdout,stderr,stdin, feof and related.
Added `reset' to the libfcgi input stream so that it is possible to reset previous errors.
2013-12-03 10:45:52 +01:00
4f15745647 For Nino connector, ensured that environment variables are percent-encoded in meta variables. 2013-12-02 10:26:23 +01:00
20367851cc fixed compilation of libfcgi tests. 2013-11-20 09:17:41 +01:00
2978ec33b7 Accept again detachable argument for HTTP_AUTHORIZATION.make (..) to avoid breaking existing code.
Note that HTTP_AUTHORIZATION.http_authorization is now detachable.
2013-11-20 09:17:28 +01:00
3d126b04a9 fixed compilation of the filter example 2013-11-20 09:16:28 +01:00
33fd3c8009 The "not implemented" response, now also precise the request method. 2013-11-19 22:08:06 +01:00
ea1c8a23cd http_client: changed some default settings connect_timeout' and timeout' to 0 (never timeout)
Updated comments
2013-11-19 22:07:29 +01:00
1827723ccc Fixed compilation of restbucksCRUD for the policy driven framework target. 2013-11-19 22:00:33 +01:00
Jocelyn Fiat
949d3514b8 Merge branch 'master' of https://github.com/Eiffel-World/EiffelWebNino 2013-11-18 17:41:19 +00:00
Jocelyn Fiat
7818b9dc1c removed CRLF eol in many files 2013-11-18 17:40:32 +00:00
Jocelyn Fiat
d15da0ffd4 merged wiki page changes 2013-11-18 17:34:03 +00:00
Jocelyn Fiat
a0665313ed Merge branch 'master' of https://github.com/eiffelhub/json 2013-11-18 17:30:37 +00:00
Jocelyn Fiat
8a7bd30ce0 native eol 2013-11-18 17:28:37 +00:00
f2da98c387 Fixed wrong assertion related to upload_data and upload_filename in HTTP_CLIENT_REQUEST_CONTEXT .
Fixed issue #124
Enable all assertion for the related autotest cases.
2013-11-12 21:37:39 +01:00
YNH Webdev
51c4e8ab9e Rename files 2013-11-11 08:28:08 +01:00
YNH Webdev
f369b26d88 Rename validators, Make forms resizable 2013-11-10 17:22:28 +01:00
YNH Webdev
40bb88a55f Validate all fields and make regexp stricter 2013-11-10 16:53:21 +01:00
YNH Webdev
72e7493842 Fix event handler 2013-11-10 16:39:04 +01:00
YNH Webdev
6213021f45 Fix form element control 2013-11-10 15:10:00 +01:00
YNH Webdev
eb3fb7e5f7 Update sample app 2013-11-10 13:58:44 +01:00
YNH Webdev
1ec14ec397 Fix email validation and min and max validator 2013-11-10 13:53:20 +01:00
YNH Webdev
38f422896d Fix slider 2013-11-09 17:14:58 +01:00
YNH Webdev
3895cf4399 Fix assert path 2013-11-09 14:42:17 +01:00
YNH Webdev
7e69fddac9 Fix rendering issue. Add active class 2013-11-08 23:03:30 +01:00
e6f1a06545 Fixed issue with unicode login:password
Added EIS info
Added testing cases.
2013-11-08 18:14:40 +01:00
e20dd076c3 Updated gewf source code to allow custom settings,
and in particular the location of the templates.
Fixed compilation of application launcher, and make it more flexible.
2013-11-08 16:16:45 +01:00
jvelilla
a2cc3d8b29 Added DEBUG_OUTPUT to JSON_OBJECT 2013-11-08 10:38:44 -03:00
jvelilla
fa4cbd8fa8 Updated readme file 2013-11-08 09:57:27 -03:00
jvelilla
884b6b1339 Merge branch 'master' of https://github.com/eiffelhub/json 2013-11-08 09:55:21 -03:00
jvelilla
9576779cce Merge pull request #7 from ynh/simplify_json_object
Simplify the json object by adding type specific put and replace
2013-11-08 04:54:59 -08:00
YNH Webdev
0721384b60 Adjust layout control and fix navlist 2013-11-08 09:27:56 +01:00
YNH Webdev
0d79799a5d Fix autocomplete 2013-11-08 00:09:09 +01:00
YNH Webdev
86339d8163 Redesign states and implement generated control_name 2013-11-08 00:03:02 +01:00
jvelilla
64bde6220c Merge branch 'master' of https://github.com/eiffelhub/json 2013-11-07 19:19:50 -03:00
jvelilla
3406780f65 Updated comments, add DEBUG_OUPUT to JSON_ARRAY. 2013-11-07 19:18:20 -03:00
Jocelyn Fiat
597e0e82b9 cosmetic and indexing note description 2013-11-07 23:14:50 +01:00
jvelilla
137af843af Fixed normalized line endings 2013-11-07 18:14:59 -03:00
jvelilla
8a96ed87b1 Normalize line endings 2013-11-07 17:55:15 -03:00
jvelilla
59b0d0d9fa Added gitattribute configuration file 2013-11-07 17:38:02 -03:00
YNH Webdev
c9102af0aa Add stateless widgets 2013-11-06 15:44:31 +01:00
severin
6838089570 Fix Layout Control 2013-11-05 16:14:15 +01:00
severin
aba60a473a Added navlist widget 2013-11-05 16:05:24 +01:00
YNH Webdev
9a392ba292 Fix project 2013-11-05 15:50:28 +01:00
severin
85369d5247 Added WSF_LAYOUT_CONTROL 2013-11-05 15:39:42 +01:00
YNH Webdev
7c11de3073 Fix navbar state problem 2013-11-04 00:22:42 +01:00
YNH Webdev
4d07a6330d Add item alias 2013-11-03 12:51:35 +01:00
severin
dad4191c40 Fixed js 2013-11-02 23:02:07 +01:00
severin
b70450cfe9 Added dropdown control 2013-11-02 22:36:21 +01:00
severin
10b950a7e7 Fixed creation procedures (make) 2013-11-02 18:34:48 +01:00
YNH Webdev
1b831375ef Fix image sizes 2013-10-30 13:35:53 +01:00
YNH Webdev
a979bf24d4 Fix slider code 2013-10-30 13:14:48 +01:00
severin
4b11bbb73d Slider fix 2013-10-30 13:02:49 +01:00
YNH Webdev
f1cefd6173 Fix path 2013-10-29 23:14:45 +01:00
severin
ac31e1c29e Merge branch 'widget_slider' into widget
Conflicts:
	draft/library/wsf_js_widget/kernel/webcontrol/wsf_control.e
	examples/widgetapp/base_page.e
2013-10-29 15:39:32 +01:00
severin
61f032a819 Fixed WSF_MULTI_CONTROL (wrong order of subcontrols), completed navbar, improved slider 2013-10-29 15:32:57 +01:00
026f8ae608 Fixed WSF_FILE_SYSTEM_HANDLER.process_index (..) 2013-10-25 16:09:43 +02:00
ab07c2e0ce Added content_negotiation to official EWF release. 2013-10-25 16:08:16 +02:00
637303930a Removed trimmed_string function and callers, and for now, use (left_|right_)adjust 2013-10-24 17:33:27 +02:00
Jocelyn Fiat
78ee9872bd Merge pull request #83 from jvelilla/master
Contracts, comments and cosmetic
2013-10-23 03:48:26 -07:00
4dd1731e60 Removed trimmed_string function and callers, and for now, use (left_|right_)adjust 2013-10-23 12:46:36 +02:00
jvelilla
2c2770b4f1 Reuse trimmed_string from HTTP_HEADER_UTILITIES.
Added description to FITNESS_AND_QUALITY.
2013-10-22 08:35:03 -03:00
jvelilla
8c04a9183f Merge branch 'master' of https://github.com/EiffelWebFramework/EWF 2013-10-21 08:50:17 -03:00
Jocelyn Fiat
373e13208f Updated Tasks Roadmap (markdown) 2013-10-21 02:52:38 -07:00
Jocelyn Fiat
250d41c2d7 Updated roadmap (markdown) 2013-10-21 02:51:50 -07:00
Jocelyn Fiat
9329ea946e Created roadmap (markdown) 2013-10-21 02:51:37 -07:00
ddd19023b0 Merge branch 'content_nego_review'
Conflicts:
	library/network/protocol/content_negotiation/src/conneg_server_side.e
	library/network/protocol/content_negotiation/src/parsers/common_accept_header_parser.e
	library/network/protocol/content_negotiation/test/conneg_server_side_test.e
2013-10-18 21:30:10 +02:00
9b329c8b8a Merge branch 'master' of github.com:EiffelWebFramework/EWF 2013-10-18 21:05:26 +02:00
6f48cf80f2 Added content_negotiation in "wsf" library 2013-10-18 21:04:00 +02:00
464cbcae80 Minor changes in wsf test cases. 2013-10-18 21:02:55 +02:00
8c57856232 Reintroduced WSF_SERVICE.to_wgi_service: WGI_SERVICE
since it was used in the "WSF" test cases.
2013-10-18 21:02:05 +02:00
4f490aaacc Fixed issue related to {WSF_WGI_DELAYED_HEADER_RESPONSE} and filter response like the logger response wrapper.
issue#82
2013-10-18 21:01:23 +02:00
3065637c80 Fixed an issue with one short chunk and empty trailer
issue#81
2013-10-18 20:59:29 +02:00
cf01756c1c Using the new Content Negotiation library to implement WSF_REQUEST.is_content_type_accepted 2013-10-18 20:46:08 +02:00
58dc2ec792 Updated README.md for conneg 2013-10-18 20:44:36 +02:00
88e6837222 Class renaming for content_negotiation
Splitted SERVER_CONTENT_NEGOTIATION in 4 differents classes for each kind of negotiation
Changed to use ITERABLE over LIST for supported variants arguments
Factorized some code for http parameter parsing such as q=1.0;note="blabla"  and so on
Integrated within EWF
2013-10-18 16:18:22 +02:00
d376f99832 Updated content_negotiation with better class names and feature names.
Minor semantic changes in VARIANTS classes
Factorized some code in HTTP_ACCEPT_LANGUAGE
2013-10-15 23:19:12 +02:00
3072ce7dec Enabled assertion on content_negotiation during autotests
The tests project is now void-safe

Using force instead of put_left seems to work fine
  and is better for performance,
  and no need to check for precondition "not before"
2013-10-14 18:54:36 +02:00
jvelilla
82fdd53adb revert previous change 2013-10-04 12:53:31 -03:00
jvelilla
b97073b14a Assertions turn on. 2013-10-04 12:32:37 -03:00
jvelilla
9a10e6f2a3 Merge pull request #80 from jvelilla/master
Fixed issue# 79 Bug in CONNEG_SERVER_SIDE
2013-10-04 06:29:25 -07:00
jvelilla
60d77892e5 Fixed issue# 79 Bug in CONNEG_SERVER_SIDE 2013-10-04 10:24:19 -03:00
Jocelyn Fiat
9e11931b44 Merge pull request #78 from colin-adams/errors
When custom error is created in check_resource_exists, use it
2013-10-02 13:21:44 -07:00
Colin Adams
8fe7f4db82 When custom error is created in check_resource_exists, use it 2013-10-01 08:40:16 +01:00
Severin
26e6a62e6b Test 2013-09-29 02:24:33 +02:00
Olivier Ligot
d26c68cd1e Start to write documentation about connectors 2013-09-28 16:40:02 +02:00
YNH Webdev
01327a4b06 Add codeview 2013-09-28 16:24:51 +02:00
YNH Webdev
d3299f8e06 Fix news datasource 2013-09-28 09:49:53 +02:00
YNH Webdev
1100328fee Fix load state error 2013-09-28 09:44:39 +02:00
YNH Webdev
cb1a4825d2 Implement lazy js load wraper 2013-09-28 00:45:27 +02:00
YNH Webdev
aa9f4c4ed8 Load needed libraries dynamically 2013-09-28 00:30:29 +02:00
Severin Münger
c6d59d3366 Fixed slider 2013-09-27 18:13:55 +02:00
YNH Webdev
8353f34c45 Adjust widgetapp 2013-09-27 11:02:10 +02:00
YNH Webdev
b6c082e1fe Create new JSON_OBJECT 2013-09-27 10:57:40 +02:00
YNH Webdev
48251fb872 Add boolean 2013-09-27 10:25:36 +02:00
jvelilla
f14728c1a7 Merge pull request #76 from jvelilla/master
Fixed Issue #75 CONNEG doesn't handle accept encodings correcty
2013-09-25 12:20:04 -07:00
jvelilla
295e6e9198 Added more scenarios to test accept encoding with identity. 2013-09-25 16:15:27 -03:00
jvelilla
e21af4a0e8 Fixed Issue #75 CONNEG doesn't handle accept encodings correcty 2013-09-25 15:22:57 -03:00
YNH Webdev
805ac5dacf Remove remaining detachable variables 2013-09-25 12:52:17 +02:00
YNH Webdev
93f8cd789f Make types attached 2013-09-25 12:50:17 +02:00
YNH Webdev
7b0d264aab Fix formating 2013-09-25 10:08:10 +02:00
YNH Webdev
4d0dc964da Rename procedures. Change input type of replace_with_string and
put_string
2013-09-25 10:03:38 +02:00
YNH Webdev
95fd5f93fc Simplify the json object by adding type specific put and replace 2013-09-24 21:50:36 +02:00
0f7dca0701 Removed unwanted call to RT_DEBUGGER in WSF_DEBUG_HANDLER.
This line was committed by error.
2013-09-24 17:19:29 +02:00
843955b7b8 Reused string constants from HTTP_HEADER_NAMES 2013-09-24 15:27:02 +02:00
88192335b6 Added implicit conversion from agent to WSF_URI_TEMPLATE_AGENT_HANDLER
Mainly for convenience.
2013-09-24 15:26:16 +02:00
b04159fb35 Use WSF_RESPONSE.put_header_lines (header_object) when possible, instead of put_header_text (header_object.string) 2013-09-24 15:24:34 +02:00
1d0eb14918 Added WSF_SELF_DOCUMENTED_AGENT_HANDLER and variants for uri, uri_template, starts_with, ...
to provide a way to documentate easily wsf agent handler.
2013-09-24 15:23:15 +02:00
YNH Webdev
113df6efe1 Merge branch 'widget' of github.com:souvarin/EWF into widget 2013-09-24 15:20:43 +02:00
Jocelyn Fiat
e7951338c9 Merge pull request #74 from jvelilla/master
Added description to results classes.
Removed unnecessary classes
Clean code: removed feature out, updated corresponding test cases.
2013-09-24 06:18:20 -07:00
Severin Münger
83329ca4b7 Moved to draft 2013-09-24 15:18:14 +02:00
Severin Münger
f51201eae1 Removed WSF_STATELESS_MULTI_CONTROL 2013-09-24 15:02:33 +02:00
Severin Münger
c52a513378 Changed slider 2013-09-24 14:38:01 +02:00
Severin Münger
6908bfe7bf Added slider demo 2013-09-24 02:38:36 +02:00
Severin Münger
a5fa428e98 Added simple image slider widget 2013-09-24 01:28:29 +02:00
YNH Webdev
24f760c043 Add table title 2013-09-24 00:22:56 +02:00
YNH Webdev
3f089d6811 Implement remove 2013-09-24 00:18:38 +02:00
YNH Webdev
7e673b4628 Stop interval if deleted 2013-09-23 00:40:40 +02:00
YNH Webdev
ca633d3524 Introduce actions
First working modal
2013-09-23 00:15:43 +02:00
YNH Webdev
7dd726ca42 Set url within page class 2013-09-22 22:47:29 +02:00
YNH Webdev
3f6caa76dc Fix confict 2013-09-22 19:14:19 +02:00
YNH Webdev
5a18cb4246 Merge branch 'widget' of github.com:souvarin/EWF into widget_state_redesign
Conflicts:
	examples/widgetapp/base_page.e
2013-09-22 19:11:46 +02:00
YNH Webdev
b33de9985f Implement control isolation 2013-09-22 19:11:07 +02:00
YNH Webdev
3a9ede6e8c Restructure callbacks 2013-09-22 18:30:48 +02:00
Severin Münger
87569ccee9 Merge branch 'widget' of github.com:ynh/EWF into widget 2013-09-22 18:20:53 +02:00
Severin Münger
16b79ef193 Improved Navbar, changed attribute handling 2013-09-22 18:20:17 +02:00
YNH Webdev
f360e8a867 Add comments to grid controls 2013-09-22 14:35:26 +02:00
Severin Münger
57dd4ce259 Added comments to autocompletion, input, navbar, progressbar, validator, webcontrol. Some more little changes. 2013-09-21 23:01:36 +02:00
YNH Webdev
252b5ff758 Use append 2013-09-20 20:53:51 +02:00
YNH Webdev
b19598d902 Fix tuple 2013-09-20 20:51:19 +02:00
YNH Webdev
b5ef1fbbb5 Make recommended changes
- Implicit casting
- Use same_string
2013-09-20 20:49:03 +02:00
jvelilla
bc864bde39 Added description to results classes.
Removed unnecessary class
Clean code: removed feature out, updated corresponding test cases.
2013-09-20 15:34:00 -03:00
YNH Webdev
0a2883e040 Rename clusters to singular names 2013-09-20 19:22:46 +02:00
YNH Webdev
24474e6b31 Move project to wsf_js_widget 2013-09-20 19:19:34 +02:00
dd31970b01 Renamed content_negotation' as content_negotiation' (fixed typo)
Updated .ecf and Eiffel code depending on previous CONNEG
2013-09-20 15:18:56 +02:00
f31ed103d0 Integrated changes on content negociation library 2013-09-20 15:04:50 +02:00
ynh
6c0eeebf27 Merge pull request #2 from jocelyn/widget_first_review
Minor changes
2013-09-20 03:34:36 -07:00
48f5cb78d5 Minor changes
- using http_client library instead of libcurl directly
 - using implicit conversion to JSON_STRING to improve code readability
 - use ARRAYED_LIST instead of LINKED_LIST .. for performance.
 - cosmetic .. but still a lot of feature clauses are missing, comments, assertions ...
2013-09-20 10:27:00 +02:00
jvelilla
20a768749f Forgot to add class description 2013-09-19 15:16:26 -03:00
jvelilla
2d964b1137 Removed http classes related to http expectations.
Updated code based on the code review.
Still work in progress
2013-09-19 13:44:03 -03:00
jvelilla
a1245b77fd New directory structure (variants, results, parsers)
Refactor STRING to READABLE_STRING_8.
Clean code, added documentation and EIS references.
2013-09-17 10:09:46 -03:00
jvelilla
f2ee91764d Renamed CONNEG to content_negotiation.
Update MIME_PARSER to use HTTP_MEDIA_TYPE.
2013-09-16 23:56:01 -03:00
fff08a29e7 Accepts "*" as valid media type (interpreted as */* to be flexible) 2013-09-16 22:33:18 +02:00
jvelilla
a6260ed5a2 Merge branch 'master' of https://github.com/EiffelWebFramework/EWF 2013-09-16 13:08:09 -03:00
2f3a462c42 Fixed type having a semicolon in a parameter value such as
"text/plain; param1=%"something;foo=bar%"; param2=%"another-thing%"
2013-09-16 18:04:43 +02:00
jvelilla
37e6d74a34 Merge branch 'master' of https://github.com/EiffelWebFramework/EWF 2013-09-16 11:26:18 -03:00
f8a0bbf88b Added autotests to http library in relation with mime type and content type.
Fixed an issue with more than one parameter.
2013-09-16 16:24:05 +02:00
jvelilla
cbd7dc8176 Merge branch 'master' of https://github.com/EiffelWebFramework/EWF 2013-09-16 09:16:38 -03:00
YNH Webdev
1da678f726 Slow down fetching 2013-09-16 00:01:31 +02:00
Severin Münger
fccb6776b0 Fixed progressbar 2013-09-15 23:47:04 +02:00
Severin Münger
f2e85aca42 Merge branch 'widget' of github.com:ynh/EWF into widget 2013-09-15 22:14:07 +02:00
Severin Münger
2fbffb8c9e Added progress callback 2013-09-15 22:13:51 +02:00
YNH Webdev
dd8bddd45c Make js files local 2013-09-15 18:33:39 +02:00
YNH Webdev
358fe04699 Add all countries to flag list
Set encoding (Must be changed to UTF-8 in future)
2013-09-15 17:32:23 +02:00
YNH Webdev
647beea245 Rearrange demo
Add contact autocompletion
2013-09-15 15:25:13 +02:00
YNH Webdev
251974fd2f Create basepage 2013-09-15 14:16:18 +02:00
YNH Webdev
81952e7898 Merge branch 'widget_grid' into widget
Conflicts:
	examples/widgetapp/widget.coffee
	examples/widgetapp/widget.js
2013-09-15 14:04:45 +02:00
YNH Webdev
1ba9792547 Fix suggestions 2013-09-15 13:33:43 +02:00
Severin Münger
45e3a6d7cc Small changes 2013-09-15 13:25:01 +02:00
Severin Münger
be05edac7d Added Progress Control 2013-09-15 01:57:03 +02:00
Severin Münger
6761d22fa8 Added Progress Control 2013-09-15 01:55:17 +02:00
Severin Münger
9db93cf4c9 Included navbar example 2013-09-15 00:44:20 +02:00
YNH Webdev
15dd993b95 Fix change event 2013-09-14 22:45:58 +02:00
YNH Webdev
0f8444a585 Remove column from grid 2013-09-14 20:39:07 +02:00
YNH Webdev
6230d643c8 Style demo pages 2013-09-14 19:39:08 +02:00
YNH Webdev
cfe452543a Implement repeater 2013-09-14 18:41:49 +02:00
YNH Webdev
26ec7d94c6 Google news example 2013-09-14 17:46:57 +02:00
YNH Webdev
95f823e7a1 - Add event paramenter
- Implement Paging control
2013-09-14 14:27:11 +02:00
Severin Münger
09544ba6d2 Fixed rendering, added navbar 2013-09-13 23:24:49 +02:00
YNH Webdev
15676a7c9e Fix path in project 2013-09-13 19:42:24 +02:00
b5bdf88bf4 Merge branch 'master' of github.com:EiffelWebFramework/EWF 2013-09-13 14:50:29 +02:00
74e96d7816 Added PATCH support in http_client, and provided custom_with_upload_data and custom_with_upload_file. 2013-09-13 14:50:07 +02:00
527e877b30 forget about older version of Eiffel cURL 2013-09-13 14:49:09 +02:00
Severin Münger
efc1550ab9 Merge branch 'widget' of github.com:ynh/EWF into widget
Conflicts:
	library/server/wsf_html/webcontrol/wsf_control.e
2013-09-13 01:12:26 +02:00
Severin Münger
f53974b138 Small changes/fixes 2013-09-13 01:08:18 +02:00
YNH Webdev
6860860161 Fix render function 2013-09-13 01:05:35 +02:00
Severin Münger
9c65194d91 Small fix removed DOCTYPE 2013-09-13 00:41:31 +02:00
Severin Münger
b1cf630443 New Control structure 2013-09-13 00:28:37 +02:00
YNH Webdev
b3e383ea82 Merge branch 'widget' of github.com:souvarin/EWF into widget
Conflicts:
	library/server/wsf_html/wsf_html-safe.ecf
2013-09-13 00:21:58 +02:00
YNH Webdev
36368aff0b Add Grid Widget 2013-09-13 00:20:27 +02:00
Severin Münger
162735b328 Extended autocompletion with customized templates 2013-09-12 17:15:05 +02:00
Severin Münger
27023283e7 Autocompletion 2013-09-12 14:58:35 +02:00
Severin Münger
8fc405fef1 Changed structure 2013-09-12 11:38:31 +02:00
oligot
44d8903a10 Created Filter (markdown) 2013-09-12 02:18:05 -07:00
Olivier Ligot
113c52f6b0 README.md: Remove dot in the community section 2013-09-12 10:27:45 +02:00
Olivier Ligot
e29a4c8c8a Added Community section to the README.md file 2013-09-12 10:25:17 +02:00
9499601daf Fixing handling of query parameter without value
Issue#70 https://github.com/EiffelWebFramework/EWF/issues/70
2013-09-09 15:51:20 +02:00
jvelilla
0887f7d22f Moved Selenium web driver to WebDriver-Eiffel repository 2013-09-08 11:44:46 -03:00
jvelilla
327ecff63a Merge branch 'master' of https://github.com/EiffelWebFramework/EWF 2013-09-06 21:57:43 -03:00
Severin Münger
55e91bff7f Merge branch 'widget' of github.com:ynh/EWF into widget 2013-09-06 23:34:50 +02:00
YNH Webdev
8b179fd98d Min/Max validator 2013-09-06 21:47:02 +02:00
Severin Münger
e5841f2dad Merge branch 'widget' of github.com:ynh/EWF into widget
Conflicts:
	examples/widgetapp/sample_page.e
2013-09-06 20:40:43 +02:00
Severin Münger
d45405f261 Some small changes 2013-09-06 20:36:04 +02:00
YNH Webdev
133ed9a0be Show server side error in validation box 2013-09-06 18:52:59 +02:00
YNH Webdev
33220b2b8e Add HTML control 2013-09-06 18:45:14 +02:00
YNH Webdev
f542975872 Small render fix 2013-09-06 18:13:23 +02:00
ed9fac0545 fixed compilation of wsf_extension 2013-09-06 18:13:05 +02:00
YNH Webdev
4dd4678b65 Comment js code 2013-09-06 18:09:39 +02:00
YNH Webdev
bbd48d24e4 Implement serverside and client side validatation 2013-09-06 18:06:43 +02:00
3b66d77ddc Merge branch 'master' of github.com:EiffelWebFramework/EWF 2013-09-06 15:40:23 +02:00
fc5ef995bc Added WSF_CUSTOM_HEADER_FILTER which provide a convenient way to add a custom header from a filter.
Added to wsf_extension WSF_DEBUG_FILTER and WSF_DEBUG_HANDLER that could be convenient to test specific requests
Restructured wsf_extension
2013-09-06 15:39:04 +02:00
4c5fa0ed61 added policy driven license .lic files 2013-09-06 15:35:09 +02:00
ea9161b2f2 Added WSF_WIDGET_RAW_TEXT to render text via html encoding.
Added WSF_WIDGET_COMPOSITE.extend_html_text (READABLE_STRING_8) that should replace the now obsolete "extend_text"
Added WSF_WIDGET_COMPOSITE.extend_raw_text (READABLE_STRING_GENERAL), for text that need to be html encoded during html rendering.
Made WSF_FORM_RAW_TEXT obsolete.
2013-09-06 15:34:38 +02:00
3c139315e5 removed useless (and unused) function {WSF_SERVICE}.to_wgi_service: WGI_SERVICE 2013-09-06 15:32:05 +02:00
15a96a402d Fixed bad output 2013-09-06 15:31:26 +02:00
5959099c55 Used res.put_header_lines (h) rather than res.put_header_text (h.string) 2013-09-06 15:31:11 +02:00
YNH Webdev
9f40c6355c First working checkbox list 2013-09-06 14:22:23 +02:00
YNH Webdev
0fcb80aa29 Merge branch 'widget' of github.com:souvarin/EWF into widget 2013-09-06 12:29:14 +02:00
Severin Münger
59a12dcac1 Added checkbox list, modified form validation 2013-09-06 01:20:41 +02:00
YNH Webdev
eb47c101ca Merge branch 'widget' of github.com:souvarin/EWF into widget 2013-09-05 23:37:19 +02:00
Severin Münger
c67a7f4982 Added validators for decimals and mails 2013-09-05 22:57:56 +02:00
Severin Münger
aba394502c Added Regexp validation (later used for mail, numbers...) 2013-09-05 22:09:08 +02:00
YNH Webdev
0c265f4f78 Fix form and textarea bug 2013-09-05 17:43:46 +02:00
YNH Webdev
32518cfb41 Merge branch 'widget' of github.com:souvarin/EWF into widget
Conflicts:
	library/server/wsf_html/webcontrol/wsf_control.e
2013-09-05 17:20:40 +02:00
YNH Webdev
225f821206 Test the new controls 2013-09-05 17:18:46 +02:00
Severin Münger
f506d9e925 Implemented WSF_CHECKBOX_CONTROL, added id attribute to rendering of WSF_CONTROL 2013-09-05 17:16:56 +02:00
YNH Webdev
edce18fb1f Merge branch 'widget' of github.com:ynh/EWF into widget 2013-09-05 16:53:29 +02:00
YNH Webdev
ad15ab13c5 Fix render function 2013-09-05 16:53:05 +02:00
Severin Münger
f52f6512a0 Restructured validators, fixed form element rendering 2013-09-05 16:51:51 +02:00
YNH Webdev
7bdafbd21e Fix render function 2013-09-05 16:51:37 +02:00
YNH Webdev
6486c8c472 Merge branch 'widget' of github.com:souvarin/EWF into widget 2013-09-05 16:28:21 +02:00
YNH Webdev
fb345c5f0c Add bootstrap 2013-09-05 16:27:55 +02:00
Severin Münger
deaeaa434d Implemented WSF_FORM_ELEMENT_CONTROL 2013-09-05 16:25:44 +02:00
Severin Münger
f9cc0afb9e Merge branch 'widget' of github.com:ynh/EWF into widget
Conflicts:
	library/server/wsf_html/webcontrol/wsf_control.e
	library/server/wsf_html/webcontrol/wsf_text_control.e
2013-09-05 15:40:11 +02:00
Severin Münger
ee0400463f Began with implementation of form handling 2013-09-05 15:37:59 +02:00
YNH Webdev
fa35c22d2d Use render tag 2013-09-05 15:33:56 +02:00
Severin Münger
422b73058c Adapted rendering of multi control 2013-09-05 15:12:22 +02:00
Severin Münger
c50a46206d Merge branch 'widget' of github.com:ynh/EWF into widget 2013-09-05 15:08:24 +02:00
Severin Münger
f866c067cb Changed creation procedures 2013-09-05 15:08:02 +02:00
YNH Webdev
811d087d74 Generate tag 2013-09-05 14:55:52 +02:00
YNH Webdev
633243311d Change wsf control 2013-09-05 14:48:19 +02:00
oligot
f5d5381fae Updated Router (markdown) 2013-09-04 05:04:21 -07:00
oligot
bbc3249212 Updated Router (markdown) 2013-09-04 05:01:42 -07:00
oligot
625b8803df Updated Request and response (markdown) 2013-09-04 04:59:59 -07:00
oligot
0d8090b6f4 Updated Request and response (markdown) 2013-09-04 04:59:14 -07:00
oligot
718c0af085 Updated Request and response (markdown) 2013-09-04 04:59:04 -07:00
oligot
5a94264dc0 Created Router (markdown) 2013-09-04 04:55:14 -07:00
oligot
8269f3ea5b Updated Connectors (markdown) 2013-09-04 04:54:04 -07:00
oligot
d6333362a7 Created Request and response (markdown) 2013-09-04 04:53:30 -07:00
oligot
3e43fd52ae Created Connectors (markdown) 2013-09-04 04:52:22 -07:00
Olivier Ligot
1111333223 Contribute page 2013-09-04 13:38:44 +02:00
Severin Münger
ae9952a941 Added class for TextArea 2013-09-03 03:54:33 +02:00
Severin Münger
3b2ad80dc3 Added TextArea 2013-09-03 03:53:01 +02:00
Severin Münger
1c08439c1a forgot to add new files 2013-09-02 20:25:59 +02:00
Severin Münger
16c89180d2 Added generalized input control similiar to text 2013-09-02 03:44:30 +02:00
YNH Webdev
bc6b4f90c3 Only send changes back to client 2013-08-29 18:31:57 +02:00
YNH Webdev
275cc7aa21 Add comments
Use Precursor
2013-08-28 22:59:24 +02:00
YNH Webdev
e186475a81 Clean up code
Simplify event
2013-08-28 19:43:44 +02:00
YNH Webdev
595d0c501a Only callback if there is an event attached 2013-08-28 15:57:16 +02:00
YNH Webdev
4e09a15454 Remove ugly do nothing hack 2013-08-28 15:30:13 +02:00
YNH Webdev
b7ab840d71 Communication in both directions (Text control)
Code regrouping
2013-08-28 12:52:09 +02:00
YNH Webdev
b72e6871e8 Fix multi control
Use multi control in example
2013-08-28 11:04:54 +02:00
YNH Webdev
f14ea29636 Comment and reformat coffee script file 2013-08-28 00:34:25 +02:00
YNH Webdev
cb7f1f0ee3 First working callback 2013-08-28 00:04:42 +02:00
Severin Münger
ef34217a6d Added WSF_MULTI_CONTROL to support controls that consist of multiple separate controls. 2013-08-27 22:06:08 +02:00
Severin Münger
ab7ee8e4c3 Created first working sample page application. 2013-08-27 16:48:20 +02:00
YNH Webdev
1a1df35ff1 Remove content length 2013-08-27 16:45:50 +02:00
YNH Webdev
0c0fb5c9c8 Add html body 2013-08-27 16:44:58 +02:00
YNH Webdev
c29a6ad195 Add assigner 2013-08-27 16:33:54 +02:00
YNH Webdev
6fdffb7418 Add post condition 2013-08-27 16:18:51 +02:00
YNH Webdev
8db642cf3b Move initalize controls 2013-08-27 16:07:06 +02:00
YNH Webdev
850a05d6bb Pretty Print 2013-08-27 16:00:24 +02:00
YNH Webdev
74995101d1 Add a json state to each control 2013-08-27 15:58:56 +02:00
YNH Webdev
fa5d13e19d Fix path 2013-08-27 15:01:57 +02:00
YNH Webdev
9f7e72f0a4 Page structure 2013-08-27 14:47:43 +02:00
YNH Webdev
c224bf1bb1 Test 2013-08-27 13:53:34 +02:00
Severin Münger
b5b71a3db0 Created widget-project testapp project. 2013-08-27 13:48:44 +02:00
oligot
cc1abfd1f9 Updated Web meeting 2012 09 18 (markdown) 2013-08-23 06:39:41 -07:00
oligot
771c91227e Updated Useful links (markdown) 2013-08-23 06:38:37 -07:00
oligot
1276ea0d1b Updated Tasks Roadmap (markdown) 2013-08-23 06:37:46 -07:00
oligot
611ce6eb9c Updated Projects new suggestions (markdown) 2013-08-23 06:31:09 -07:00
oligot
2870df8478 Updated Projects new suggestions (markdown) 2013-08-23 06:30:45 -07:00
oligot
59b2163a62 Updated Projects (markdown) 2013-08-23 06:29:39 -07:00
oligot
065318749b Updated Projects (markdown) 2013-08-23 06:28:49 -07:00
oligot
600ee095cc Updated Projects (markdown) 2013-08-23 06:27:03 -07:00
oligot
ecb49619da Updated Projects (markdown) 2013-08-23 06:25:31 -07:00
oligot
b73939d0a0 Updated Meetings (markdown) 2013-08-23 06:21:00 -07:00
oligot
6c83639149 Updated Home (markdown) 2013-08-23 06:16:24 -07:00
oligot
e77ee9bdf3 Updated Home (markdown) 2013-08-23 06:15:49 -07:00
oligot
9449f0d16e Updated Home (markdown) 2013-08-23 06:12:00 -07:00
oligot
4ff29e1fb3 Updated Home (markdown) 2013-08-23 06:11:23 -07:00
oligot
4de85df5b6 Updated EWSGI specification (markdown) 2013-08-23 06:07:26 -07:00
oligot
294ccb04d3 Updated EWSGI specification (markdown) 2013-08-23 06:06:49 -07:00
oligot
4f0567ad88 Updated EWSGI (markdown) 2013-08-23 06:05:10 -07:00
oligot
65c613d0a4 Links 2013-08-23 06:01:52 -07:00
oligot
a16bca2f29 Links 2013-08-23 05:48:02 -07:00
517720c99c Updated copyright for policy-driven classes, which is a contribution from Colin Adams. 2013-08-21 14:00:34 +02:00
jvelilla
86e942ae0a Merge branch 'master' of https://github.com/jocelyn/EWF 2013-08-21 08:33:53 -03:00
9938cc941d Merge branch 'master' of https://github.com/EiffelWebFramework/EWF.wiki 2013-08-21 09:58:59 +02:00
2651171294 Extracted the policy driven classes into their own library for now "wsf_policy_driven.ecf"
Updated the restbucksCRUD example to demonstrate both approaches.
2013-08-20 17:27:57 +02:00
07f71dfc4e Moved recent policy-driven classes into "policy" sub folder 2013-08-20 13:26:55 +02:00
51730e0877 Merge branch 'handler' of github.com:colin-adams/EWF into colin-adams-handler 2013-08-20 13:17:01 +02:00
9958bb27a1 Removed WSF_ROUTING_HANDLER.make_with_router (a_router)
It was not used in existing code, and potentially dangerous, if coder reuses router by accident.
2013-08-20 13:15:37 +02:00
Colin Adams
37b94bbf0d Added header comment about redefining for extension methods 2013-08-19 11:48:49 +01:00
Colin Adams
3ae898476f Changed age to max_age 2013-08-16 04:50:48 +01:00
Colin Adams
eefe547553 Changed comment on execute to check assertion 2013-08-15 14:58:58 +01:00
Colin Adams
2903a1d3cd Improved comment to ensure_content_exists - take 2 2013-08-15 10:31:40 +01:00
Colin Adams
0755e2d2bc Improved comment to ensure_content_exists 2013-08-15 10:30:47 +01:00
Colin Adams
b5957d0f59 Removed empty feature clause 2013-08-15 08:57:54 +01:00
Colin Adams
143608fd85 Fixed recursion on router bug 2013-08-14 11:32:27 +01:00
colin-adams
b2d9fe1a4b Updated Writing the handlers (markdown) 2013-08-14 02:47:12 -07:00
colin-adams
aff7948c65 Updated Writing the handlers (markdown) 2013-08-14 02:23:53 -07:00
colin-adams
bcdfcdd468 Updated Writing the handlers (markdown) 2013-08-14 02:23:07 -07:00
colin-adams
5e62d82e9c Updated Wsf previous policy (markdown) 2013-08-14 02:22:22 -07:00
Colin Adams
275c26b55b Further use of constants for execution variables 2013-08-14 09:22:35 +01:00
colin-adams
123fc8252e Updated Writing the handlers (markdown) 2013-08-13 08:24:05 -07:00
Colin Adams
c93e50a7e2 Gave symbolic names to execution variables used by the framework 2013-08-13 15:47:59 +01:00
colin-adams
9c8bc59224 Updated Writing the handlers (markdown) 2013-08-13 00:54:45 -07:00
Colin Adams
b074570e99 Added some checks for custom erros being set. 2013-08-12 16:45:47 +01:00
colin-adams
bf5bae803d Updated Writing the handlers (markdown) 2013-08-12 01:49:11 -07:00
colin-adams
35224b1b17 Updated Writing the handlers (markdown) 2013-08-12 01:45:58 -07:00
Colin Adams
2ed362f5d3 refactored to allow etags to work properly when multiple representations are available 2013-08-12 09:27:00 +01:00
colin-adams
fe971d07ec Updated Using the policy driven framework (markdown) 2013-08-11 23:55:50 -07:00
Colin Adams
f82456f352 Found another TODO - write_error_response in GET processing 2013-08-08 17:13:38 +01:00
colin-adams
bbbf958d7d Updated Using the policy driven framework (markdown) 2013-08-08 02:41:27 -07:00
Colin Adams
4c901c3130 Implemented remaining error response calls 2013-08-08 10:39:46 +01:00
Colin Adams
eade6d584c Errors corrected that were discovered in the course of writing the tutorial 2013-08-08 09:33:21 +01:00
colin-adams
9c8a034a04 Updated Writing the handlers (markdown) 2013-08-08 01:32:31 -07:00
colin-adams
2dac1ff6c9 Updated Writing the handlers (markdown) 2013-08-08 01:25:29 -07:00
colin-adams
e9013e548b Updated Writing the handlers (markdown) 2013-08-08 00:56:14 -07:00
colin-adams
bc976c37b1 Updated Writing the handlers (markdown) 2013-08-08 00:26:56 -07:00
Colin Adams
3249c377f1 made deleted into an effective routine 2013-08-08 07:31:43 +01:00
colin-adams
2415a57ab0 Updated Writing the handlers (markdown) 2013-08-07 23:30:49 -07:00
colin-adams
7e4f51a7ce Updated Writing the handlers (markdown) 2013-08-07 09:58:42 -07:00
colin-adams
10caa4c1df Updated Writing the handlers (markdown) 2013-08-07 09:48:38 -07:00
colin-adams
a552b8fcfa Updated Writing the handlers (markdown) 2013-08-07 09:13:56 -07:00
colin-adams
9395e31c53 Updated Writing the handlers (markdown) 2013-08-07 08:50:31 -07:00
colin-adams
ce04737d46 Updated Writing the handlers (markdown) 2013-08-07 07:18:35 -07:00
colin-adams
259815467c Created Wsf caching policy (markdown) 2013-08-07 07:05:24 -07:00
colin-adams
3b517d3c53 Updated Writing the handlers (markdown) 2013-08-07 06:25:31 -07:00
colin-adams
c261f02c84 Created Wsf previous policy (markdown) 2013-08-07 06:24:45 -07:00
colin-adams
7815557f84 Updated Writing the handlers (markdown) 2013-08-07 06:14:24 -07:00
colin-adams
090e294f10 Updated WSF_OPTIONS_POLICY (markdown) 2013-08-07 06:06:15 -07:00
colin-adams
33d523e5bf Updated Writing the handlers (markdown) 2013-08-07 06:03:13 -07:00
colin-adams
7bc09bda8f Created WSF_OPTIONS_POLICY (markdown) 2013-08-07 06:02:42 -07:00
colin-adams
45fd51b4b5 Updated Writing the handlers (markdown) 2013-08-07 06:02:24 -07:00
colin-adams
f3849679e8 Updated Writing the handlers (markdown) 2013-08-07 06:00:37 -07:00
colin-adams
bf0a8e8efb Updated Writing the handlers (markdown) 2013-08-07 05:57:49 -07:00
colin-adams
84c3039806 Updated Using the policy driven framework (markdown) 2013-08-07 05:51:54 -07:00
colin-adams
0c4a410ac0 Created Writing the handlers (markdown) 2013-08-07 05:51:11 -07:00
colin-adams
b55f363651 Updated Using the policy driven framework (markdown) 2013-08-07 05:30:02 -07:00
colin-adams
7dd36014cc Updated Using the policy driven framework (markdown) 2013-08-07 03:56:52 -07:00
colin-adams
78ff0134c7 Created Using the policy driven framework (markdown) 2013-08-07 03:27:42 -07:00
Colin Adams
69da6c6d06 Fixes as picked up by code review 2013-08-07 11:03:22 +01:00
Colin Adams
277eb0b4b6 restbucksCRUD example changed to use policy-driven framework 2013-08-06 15:01:24 +01:00
Colin Adams
8dbd24afd1 Policy-driven URI template handlers 2013-08-06 13:57:12 +01:00
Colin Adams
0a9d208529 New routines added to WSF_REQUEST to support ploicy-driven framework 2013-08-06 13:51:43 +01:00
Colin Adams
8ab6dba1c8 New routines added to HTTP_HEADER to support ploicy-driven framework 2013-08-06 13:49:58 +01:00
Colin Adams
e0bfdab106 Add CONNEG to wsf*.ecf to support ploicy-driven framework 2013-08-06 13:47:07 +01:00
jvelilla
fd09b39c1d Merge pull request #6 from jocelyn/patch20130805
Enhanced interface of JSON_ARRAY and JSON_OBJECT and new JSON_ITERATOR
2013-08-05 14:16:28 -07:00
8e743f3253 Enhanced interface of JSON_ARRAY and JSON_OBJECT
Added JSON_ITERATOR
2013-08-05 12:07:07 +02:00
8d9dca1a94 removed building the Clib for Eiffel cUrl, since it is not anymore included in EWF. 2013-08-05 10:21:24 +02:00
5753af3e43 Cosmetic
(removed commented line and fixed bad indentation)
2013-08-05 10:20:41 +02:00
Jocelyn Fiat
63f1976663 Merge pull request #67 from berenddeboer/master
Remove invariant violation.
2013-08-05 01:16:39 -07:00
Berend de Boer
4b87a00637 Remove invariant violation. 2013-08-03 20:09:16 +12:00
Jocelyn Fiat
8d12d1c0bc Merge pull request #66 from oligot/fcgi-osx
FastCGI connector and OS X
2013-07-31 07:45:36 -07:00
Jocelyn Fiat
2c3d5b6f59 Update README.md 2013-07-30 16:06:06 +02:00
Olivier Ligot
e8c66fa769 Fix C compilation when using libfcgi connector on OS X (#65) 2013-07-19 18:51:43 +02:00
jvelilla
09f32e7025 Merge pull request #64 from oligot/all-tests
Tests compile again (fixes #63)
2013-07-11 13:02:45 -07:00
Olivier Ligot
0fca8daeb1 Tests compile again (fixes #63) 2013-07-11 16:46:38 +02:00
jvelilla
285e295b5a Merge branch 'master' of https://github.com/EiffelWebFramework/EWF
Conflicts:
	draft/application/cms/README.md
	draft/application/cms/src/cms_session.e
	draft/src/gewf/license.lic
	library/network/http_client/src/expectation/http_client_response_expectation.e
2013-07-08 18:08:35 -03:00
Colin Adams
e6371c7adc Merge branch 'master' into handler
pull from upstream
2013-07-08 10:17:44 +01:00
Colin Adams
ab7ff11cb6 Merge branch 'master' of github.com:EiffelWebFramework/EWF
Routine merge
2013-07-08 10:17:09 +01:00
Colin Adams
ba11e84ed6 prior to merging 2013-07-08 10:17:04 +01:00
2676b16425 Moved gewf under draft/src/gewf 2013-07-05 15:13:43 +02:00
f7012e5b85 added README for gewf 2013-07-05 15:12:21 +02:00
a149d8de97 licensing and copyright 2013-07-05 15:07:14 +02:00
eea8894724 First working (but limited) tool 2013-07-05 15:06:30 +02:00
5b988ab760 Added first attempt to provide a application builder.
For now only trying to have a generic template.

Do not expect anything working for now, this is just the start of a draft
2013-07-05 12:44:09 +02:00
88a38509de Merge branch 'master' of https://github.com/EiffelWebFramework/EWF.wiki 2013-07-04 17:29:25 +02:00
Jocelyn Fiat
6dee9e85b5 Updated Doc_Getting_Started (mediawiki) 2013-07-04 07:28:37 -07:00
Jocelyn Fiat
2d795eb3c1 Updated Doc_Getting_Started (mediawiki) 2013-07-04 07:28:09 -07:00
Jocelyn Fiat
717b0f7ba8 Updated Doc_Getting_Started (mediawiki) 2013-07-04 07:27:51 -07:00
Jocelyn Fiat
2d373cab5b Updated Doc_Getting_Started (mediawiki) 2013-07-04 07:25:44 -07:00
Jocelyn Fiat
e20f45b2c3 Updated Doc_Getting_Started (mediawiki) 2013-07-04 07:08:54 -07:00
Jocelyn Fiat
917388b99e Updated Doc_Index (mediawiki) 2013-07-04 07:07:00 -07:00
Jocelyn Fiat
ed1f899534 Updated Doc_Index (mediawiki) 2013-07-04 07:05:20 -07:00
Jocelyn Fiat
60a80209dc Updated Doc_Index (mediawiki) 2013-07-04 07:04:51 -07:00
Jocelyn Fiat
e4f495b282 Created Doc_Getting_Started (mediawiki) 2013-07-04 07:04:18 -07:00
Jocelyn Fiat
0efcd3cd07 Created Doc_Index (mediawiki) 2013-07-04 07:03:22 -07:00
c216b96707 Moved the cms component to https://github.com/EiffelWebFramework/cms
This is now out of EWF repository.
2013-07-02 12:21:54 +02:00
cb3f983b91 improve file system handler to ignore .* *.swp *~ or using FUNCTION to compute the ignore behavior 2013-06-28 16:11:27 +02:00
dc25723a35 Improved Unicode support. 2013-06-28 11:32:12 +02:00
8040dd5826 Ensured that EWF compiles with 7.2
(note about ecf version
   1-10-0 void_safety="all" <-->  1-11-0 void_safety="transitional"
   1-10-0 void_safety="all" <---  1-11-1 void_safety="all"
)
2013-06-28 11:06:35 +02:00
jvelilla
42ba1588c6 Merge branch 'master' of https://github.com/EiffelWebFramework/EWF 2013-06-18 10:30:55 -03:00
jvelilla
d0fda6de66 Merge branch 'master' of https://github.com/EiffelWebFramework/EWF
Conflicts:
	draft/application/cms/cms.ecf
	draft/application/cms/example/src/web_cms.e
	draft/application/cms/src/cms_configuration.e
	draft/application/cms/src/cms_default_setup.e
	draft/application/cms/src/cms_service.e
	draft/application/cms/src/cms_setup.e
	draft/application/cms/src/handler/cms_file_system_handler.e
	draft/application/cms/src/kernel/content/format/filters/cms_html_filter.e
	draft/application/cms/src/modules/debug/debug_module.e
	draft/application/cms/src/notification/cms_email.e
	draft/application/cms/src/notification/cms_storage_mailer.e
	draft/application/cms/src/storage/cms_sed_storage.e
	draft/application/cms/src/storage/cms_storage.e
	library/runtime/process/notification_email/notification_external_mailer.e
	tools/bin/ecf_updater.exe
2013-06-18 09:56:53 -03:00
jvelilla
cef69039f5 merge 2013-06-11 11:33:27 -03:00
jvelilla
cdf3a25f88 Merge https://github.com/EiffelWebFramework/EWF 2013-06-11 11:12:15 -03:00
jvelilla
d1a0229944 Merge branch 'master' of https://github.com/jvelilla/EWF 2013-05-29 09:44:45 -03:00
jvelilla
63beaabfa0 Added command POST /session/:sessionId/modifier
Initial implementation of KeyBoard.
Added Mouse class, but not implemented.
2013-05-29 09:43:14 -03:00
jvelilla
caac696465 Update readme.md 2013-05-23 07:52:30 -03:00
jvelilla
c741e41597 Update readme.md 2013-05-23 07:50:18 -03:00
jvelilla
60fa076796 Update readme.md 2013-05-23 07:49:12 -03:00
jvelilla
7dbed3ade1 Updated command_executor
Added more examples.
2013-05-22 07:18:17 -03:00
jvelilla
a6cad7e811 Update find element examples.
Improved command executor
2013-05-20 10:46:06 -03:00
jvelilla
47da8c17ea Merge https://github.com/EiffelWebFramework/EWF 2013-05-19 10:17:52 -03:00
jvelilla
ad5b52f4e4 Added new selenium locator examples.
Fixed find_elements in WEB_DRIVER.
2013-05-18 23:12:37 -03:00
jvelilla
7679898159 Move expectation classed under a expectation cluster, added a new expectation class
for header.
2013-05-14 09:29:50 -03:00
jvelilla
d344df6e7e Added examples find by id, name and class. 2013-05-14 09:28:21 -03:00
jvelilla
e0c3c783fa Updated selenium WEB_DRIVER_WAIT, the feature until_when now use a
predicate. Updated the related example.
2013-05-13 10:47:46 -03:00
jvelilla
30663dc9fb Merge branch 'master' of https://github.com/jvelilla/EWF 2013-05-10 09:49:17 -03:00
jvelilla
8db7d0daa3 Initial implementation of HTTP RESPONSE EXPECTATIONS.
Added a class to test http client with httpbin.org and expectations
2013-05-10 09:48:28 -03:00
Colin Adams
48bc71c6e3 Merge branch 'master' into handler 2013-05-10 09:27:23 +01:00
jvelilla
2d3dadc85e Update readme.md 2013-05-08 10:48:03 -03:00
jvelilla
e5765d356f Updated documentation
This documentation is based on Selinum http://docs.seleniumhq.org/
and adapted to the Eiffel implementation.
2013-05-08 10:38:25 -03:00
jvelilla
f8f1773d18 Update readme.md 2013-05-08 10:21:23 -03:00
jvelilla
15782c7795 Update readme.md 2013-05-08 10:20:48 -03:00
jvelilla
b777e81ab1 Updated WEB_DRIVER_WAIT class, still need to be improved.
Updated Readme and the example
2013-05-08 10:10:11 -03:00
jvelilla
e29346dec8 Merge https://github.com/EiffelWebFramework/EWF 2013-05-03 10:57:19 -03:00
jvelilla
8535a8378c Improve the example, Added a new class WEB_DRIVER_WAIT, still under development.
Update web driver, to define time outs.
2013-05-03 10:43:48 -03:00
jvelilla
dcdc700bac Added a simple search example.
Updated web_driver, use the API as delegation instead of inheritance.
Updated web_element class.
2013-04-30 10:19:34 -03:00
jvelilla
31c2be768f Created new classes to represent a web driver.
Added Examples, clean code
2013-04-29 18:02:33 -03:00
jvelilla
9180667ac4 Completed low level methods, clean code. 2013-04-24 14:39:08 -03:00
jvelilla
4f79bf2add Implemented more commands from REST API JSONWireProtocol
Refactor COMMAND_EXECUTOR.
2013-04-24 11:33:39 -03:00
Colin Adams
9eaada0bdb merged from master 2013-04-24 13:54:30 +01:00
jvelilla
c7e6fe38fb Added more command from JSONWireProtol. 2013-04-23 09:09:57 -03:00
jvelilla
9e8548d65a Added more commands from the JSONWireProtocol. 2013-04-23 08:26:02 -03:00
jvelilla
3c41ca0864 Added new classes, implemented more methods from JSONWireProtol API.
Added test cases
2013-04-22 09:15:50 -03:00
jvelilla
c344ecceec Fixed errors in navigate_to_url command,
Fixed url templates in  json_wire_protocol_command.
Added test cases to AutoTest
2013-04-17 10:06:34 -03:00
jvelilla
ce2ca051f6 Fixed feature typo, improved commands, added AutoTest 2013-04-16 17:31:33 -03:00
jvelilla
c63e307179 Updated RestAPI commands 2013-04-15 16:16:16 -03:00
jvelilla
1daab0598a Improved error handling, implemented more methods from the REST API from Selenium2 2013-04-15 09:40:17 -03:00
Colin Adams
98ad77a57d If-Match implemented in skeleton handler 2013-04-13 14:49:03 +01:00
Colin Adams
b4ab4875fc If-Match implemented in skeleton handler 2013-04-13 14:48:28 +01:00
jvelilla
6ead464a6b Fixed configurations paths 2013-04-12 09:38:04 -03:00
jvelilla
3d36c353fc Initial import Selenium binding 2013-04-12 09:16:52 -03:00
oligot
0eff04c847 Add support for Apache logging: done 2013-02-03 04:10:46 -08:00
oligot
2b92ba9e62 Updated Useful links (markdown) 2012-11-22 11:28:17 -08:00
oligot
c23bf7a05d Created Useful links (markdown) 2012-11-22 04:30:08 -08:00
oligot
92cbf48b49 Updated Projects new suggestions (markdown) 2012-10-08 03:38:12 -07:00
jocelyn
1dc6ff6df1 Updated Meetings (markdown) 2012-09-19 00:25:16 -07:00
jocelyn
e72ffab2ca Updated Home (markdown) 2012-09-19 00:24:53 -07:00
jocelyn
e7a06ebc2e Updated Home (markdown) 2012-09-19 00:23:40 -07:00
jocelyn
e12e0b35ee Created Meetings (markdown) 2012-09-19 00:22:50 -07:00
jocelyn
c6dac0384b Updated Projects (markdown) 2012-09-18 23:40:52 -07:00
jocelyn
e48cee9b4a Updated Projects (markdown) 2012-09-18 23:39:45 -07:00
jocelyn
9229b66091 Updated Web meeting 2012 09 18 (markdown) 2012-09-18 13:27:01 -07:00
oligot
eea428831c Updated Web meeting 2012 09 18 (markdown) 2012-09-18 06:57:38 -07:00
jocelyn
ad12d3e16d Updated Web meeting 2012 09 18 (markdown) 2012-09-18 06:24:31 -07:00
jocelyn
b1fcedf501 Updated Web meeting 2012 09 18 (markdown) 2012-09-18 06:06:12 -07:00
jocelyn
2b00192e87 Updated Web meeting 2012 09 18 (markdown) 2012-09-18 06:04:13 -07:00
oligot
2b82e7f07f Updated Web meeting 2012 09 18 (markdown) 2012-09-17 11:42:18 -07:00
jocelyn
f820d25a9e Updated Web meeting 2012 09 18 (markdown) 2012-09-17 10:04:24 -07:00
oligot
6e76747772 Created Web meeting 2012 09 18 (markdown) 2012-09-14 01:16:00 -07:00
oligot
15d12b86aa Add support for Swagger 2012-08-24 02:54:47 -07:00
970 changed files with 91314 additions and 24379 deletions

1
.gitignore vendored
View File

@@ -3,4 +3,5 @@ tests/temp/
.svn/
*.swp
*~
*.scm
*#

142
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,142 @@
# Contributing to this project
Please take a moment to review this document in order to make the contribution
process easy and effective for everyone involved.
Following these guidelines helps to communicate that you respect the time of
the developers managing and developing this open source project. In return,
they should reciprocate that respect in addressing your issue or assessing
patches and features.
## Using the issue tracker
The issue tracker is the preferred channel for [bug reports](#bugs),
[features requests](#features) and [submitting pull
requests](#pull-requests), but please respect the following restrictions:
* Please **do not** use the issue tracker for personal support requests (use
[Stack Overflow](http://stackoverflow.com) or IRC).
* Please **do not** derail or troll issues. Keep the discussion on topic and
respect the opinions of others.
<a name="bugs"></a>
## Bug reports
A bug is a _demonstrable problem_ that is caused by the code in the repository.
Good bug reports are extremely helpful - thank you!
Guidelines for bug reports:
1. **Use the GitHub issue search** &mdash; check if the issue has already been
reported.
2. **Check if the issue has been fixed** &mdash; try to reproduce it using the
latest `master` or development branch in the repository.
3. **Isolate the problem** &mdash; ideally create a [reduced test
case](http://css-tricks.com/6263-reduced-test-cases/) and a live example.
A good bug report shouldn't leave others needing to chase you up for more
information. Please try to be as detailed as possible in your report. What is
your environment? What steps will reproduce the issue? What browser(s) and OS
experience the problem? What would you expect to be the outcome? All these
details will help people to fix any potential bugs.
Example:
> Short and descriptive example bug report title
>
> A summary of the issue and the browser/OS environment in which it occurs. If
> suitable, include the steps required to reproduce the bug.
>
> 1. This is the first step
> 2. This is the second step
> 3. Further steps, etc.
>
> `<url>` - a link to the reduced test case
>
> Any other information you want to share that is relevant to the issue being
> reported. This might include the lines of code that you have identified as
> causing the bug, and potential solutions (and your opinions on their
> merits).
<a name="features"></a>
## Feature requests
Feature requests are welcome. But take a moment to find out whether your idea
fits with the scope and aims of the project. It's up to *you* to make a strong
case to convince the project's developers of the merits of this feature. Please
provide as much detail and context as possible.
<a name="pull-requests"></a>
## Pull requests
Good pull requests - patches, improvements, new features - are a fantastic
help. They should remain focused in scope and avoid containing unrelated
commits.
**Please ask first** before embarking on any significant pull request (e.g.
implementing features, refactoring code, porting to a different language),
otherwise you risk spending a lot of time working on something that the
project's developers might not want to merge into the project.
Please adhere to the coding conventions used throughout a project (indentation,
accurate comments, etc.) and any other requirements (such as test coverage).
Adhering to the following this process is the best way to get your work
included in the project:
1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
and configure the remotes:
```bash
# Clone your fork of the repo into the current directory
git clone https://github.com/<your-username>/<repo-name>
# Navigate to the newly cloned directory
cd <repo-name>
# Assign the original repo to a remote called "upstream"
git remote add upstream https://github.com/<upstream-owner>/<repo-name>
```
2. If you cloned a while ago, get the latest changes from upstream:
```bash
git checkout <dev-branch>
git pull upstream <dev-branch>
```
3. Create a new topic branch (off the main project development branch) to
contain your feature, change, or fix:
```bash
git checkout -b <topic-branch-name>
```
4. Commit your changes in logical chunks. Please adhere to these [git commit
message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
or your code is unlikely be merged into the main project. Use Git's
[interactive rebase](https://help.github.com/articles/interactive-rebase)
feature to tidy up your commits before making them public.
5. Locally merge (or rebase) the upstream development branch into your topic branch:
```bash
git pull [--rebase] upstream <dev-branch>
```
6. Push your topic branch up to your fork:
```bash
git push origin <topic-branch-name>
```
7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
with a clear title and description.
**IMPORTANT**: By submitting a patch, you agree to allow the project owner to
license your work under the same license as that used by the project.

3138
ChangeLog

File diff suppressed because it is too large Load Diff

121
MIGRATION.md Normal file
View File

@@ -0,0 +1,121 @@
Date: 2015-mar-31
# Goal:
=======
- support safe concurrency with EWF
- provide a concurrent standalone connector
# Status:
=========
- The current version of EWF has mainly 3 connectors: CGI, libFCGI, and nino.
- CGI and libFCGI connectors does not need any concurrency support.
- But the nino connector had a pseudo concurrency support with Thread, however one could do write code that result in hasardeous concurrency execution.
So, it was decided to provide an improved Eiffel web nino connector, and update EWF design to make it concurrency compliant.
# Decisions:
============
- instead of updating current nino library, we now have a new "standalone" connector which is inspired by nino, but have support for the 3 concurrency modes: none, thread and SCOOP.
# Overview
==========
Adding support for SCOOP concurrency mode add constraints to the design, but also helps ensuring the concurrency design of EWF is correct.
As a consequence, we had to introduce a new interface WSF_EXECUTION which is instantiated for each incoming request. See its simplified interface :
<code lang="eiffel">
deferred class WSF_EXECUTION
feature -- Initialization
make (req: WGI_REQUEST; res: WGI_RESPONSE)
do
...
īnitialize
end
initialize
-- Initialize Current object.
--| To be redefined if needed.
do
end
feature -- Access
request: WSF_REQUEST
-- Access to request data.
-- Header, Query, Post, Input data..
response: WSF_RESPONSE
-- Access to output stream, back to the client.
feature -- Execution
execute
-- Execute Current `request',
-- getting data from `request'
-- and response to client via `response'.
deferred
ensure
is_valid_end_of_execution: is_valid_end_of_execution
end
end
</code>
And the related request execution routines are extracted from WSF_SERVICE which becomes almost useless. The "service" part is not mostly responsible of launching the expected connector and set optional options, and declare the type of "execution" interface.
As a result, the well known WSF_DEFAULT_SERVICE has now a formal generic that should conform to WSF_EXECUTION with a `make' creation procedure. See update code:
<code lang="eiffel">
class
APPLICATION
inherit
WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION]
redefine
initialize
end
create
make_and_launch
feature {NONE} -- Initialization
initialize
-- Initialize current service.
do
set_service_option ("port", 9090)
end
end
</code>
Where APPLICATION_EXECUTION is an implementation of the WSF_EXECUTION interface (with the `make' creation procedure).
In addition to add better and safer concurrency support, there are other advantages:
- we now have a clear separation between the service launcher, and the request execution itself.
- the WSF_EXECUTION is created per request, with two main attributes <code>request: WSF_REQUEST</code> and <code>response: WSF_RESPONSE</code>.
# How to migrate to new design
- you can check the various example from the EWF repository, there should all be migrated to new design and comparing previous and new code, this will show you how the migration was done.
- a frequent process:
- identify the root class of your service, (the class implementing the WSF_SERVICE), let us name it APPLICATION_SERVICE
- copy the APPLICATION_SERVICE file to APPLICATION_EXECUTION file.
- change the class name to be APPLICATION_EXECUTION, and replace _SERVICE occurences by _EXECUTION (note the new WSF_ROUTED_EXECUTION and so on, which are mainly migration from previous WSF_ROUTED_SERVICE .., and also WSF_FILTERED_ROUTED_EXECUTION which is new.
- replace "make_and_launch" by "make", remove the initialize redefinition if any.
- in the APPLICATION_SERVICE class, remove most of the ROUTED, FILTERED ... inheritance, and keep WSF_DEFAULT_SERVICE, with a new formal generic i.e WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION].
- in the eventual redefined initialize, remove code related to routers, filters, ...
- remove all the execution related code.
- And you should be done.
- To be short, this is mostly creating a new _EXECUTION class, and move the execution related code into this class from the _SERVICE class.
- Then, you can replace the usage of nino connector by using the new "Standalone" connector, and switch to SCOOP concurrency mode, to ensure you are not messing up with concurrency. Your own code/libraris may not be SCOOP compliant, we recommend to migrate to SCOOP, but as an intermediate solutioņ, you can use the other concurrency mode (none or thread).
Note: the new design impacts the _SERVICE classes, connectors, but WSF_REQUEST, WSF_RESPONSE , WSF_ROUTER are compatible, so the migration is really easy.
We may take the opportunity to update the design deeper according to user feedback, and eventually "wsf" library will be renamed "wsf2".
This is work in progress, all comments , feedback, suggestions, bug report are welcome.
Hopefully before the final version of the new design is out.

View File

@@ -3,6 +3,27 @@
## Overview
The Eiffel Web Framework (EWF) provides Eiffel users with a layer to build anything on top of the http protocol such as websites, web API/services.
This layer is multi-platform: it can be set on Windows, Linux operating systems, and in addition it can run on top of any httpd servers such as Apache2, IIS, nginx, lighttpd. EWF includes as well a standalone httpd web server component, written in Eiffel, which enables users to run easily a web server on their machine, or even embed this component in any application written with Eiffel.
Currently EWF offers a collection of Eiffel libraries designed to be integrated with each others, and among other functionalities, it give simple access to the request data, to handle content negotiation, url dispatcher, integrate with openid system, and so on.
There is a growing ecosystem around EWF, that provides useful components:
* OpenID and OAuth consumer library
* Various hypermedia format such as HAL, Collection+json, …
* Websocket server and client
* Template engine
* API Auto-documentation with swagger
* A simple experimental CMS.
* ...
So if you want to build a website, a web api, RESTful service, …or even if you want to consume other web api, EWF is a solution.
EWF brings with it all the advantages of the Eiffel technology and tools with its powerful features such as Design by Contract, debugging, testing tools which enable to build efficient systems expected to be repeatedly refined, extended, and improved in a predictable and controllable way so as to become with time bugfree systems. Enjoy the full power of debugging your web server application from the IDE.
## Project
Official project site for Eiffel Web Framework:
* http://eiffelwebframework.github.com/EWF/
@@ -14,26 +35,21 @@ For more information please have a look at the related wiki:
For download, check
* https://github.com/EiffelWebFramework/EWF/downloads
Tasks and issues are managed with github issue system
* See https://github.com/EiffelWebFramework/EWF/issues
* And visual dashboard: https://waffle.io/eiffelwebframework/ewf
* Forum/group post: https://groups.google.com/forum/#!forum/eiffel-web-framework
## Requirements
* Compiling from EiffelStudio 7.0
* Developped using EiffelStudio 7.1 (on Windows, Linux)
* Tested using EiffelStudio 7.1 with "jenkins" CI server (not anymore compatible with 6.8 due to use of `TABLE_ITERABLE')
* Compiling from EiffelStudio 13.11 to 15.05 and more recent version of the compiler.
* Currently being developped using EiffelStudio 15.01 (on Windows, Linux)
* Tested using EiffelStudio 15.01 with "jenkins" CI server (not anymore compatible with 6.8 due to use of `TABLE_ITERABLE')
* The code have to allow __void-safe__ compilation and non void-safe system (see [more about void-safety](http://docs.eiffel.com/book/method/void-safe-programming-eiffel) )
## How to get the source code?
Using git version >= 1.6.5
* git clone --recursive https://github.com/EiffelWebFramework/EWF.git
Otherwise, try
Using git
* git clone https://github.com/EiffelWebFramework/EWF.git
* cd Eiffel-Web-Framework
* git submodule update --init
* git submodule foreach --recursive git checkout master
An alternative to the last 2 instructions is to use the script from tools folder:
* cd tools
* update_git_working_copy
* And to build the required and related Clibs
* cd contrib/ise_library/cURL
@@ -51,7 +67,7 @@ An alternative to the last 2 instructions is to use the script from tools folder
### protocol
* __http__: HTTP related classes, constants for status code, content types, ... [read more](library/protocol/http)
* __uri_template__: URI Template library (parsing and expander) [read more](library/protocol/uri_template)
* __CONNEG__: CONNEG library (Content-type Negociation) [read more](library/protocol/CONNEG)
* __CONNEG__: Content negotiation library (Content-type Negociation) [read more](library/protocol/content_negotiation)
### client
* __http_client__: simple HTTP client based on cURL [read more](library/client/http_client)
@@ -59,10 +75,6 @@ An alternative to the last 2 instructions is to use the script from tools folder
### text
* __encoder__: Various simpler encoders: base64, url-encoder, xml entities, html entities [read more](library/text/encoder)
### crypto
* eel
* eapml
### Others
* error: very simple/basic library to handle error
@@ -75,6 +87,24 @@ An alternative to the last 2 instructions is to use the script from tools folder
## Examples
..
## Contributing to this project
Anyone and everyone is welcome to contribute. Please take a moment to
review the [guidelines for contributing](CONTRIBUTING.md).
* [Bug reports](CONTRIBUTING.md#bugs)
* [Feature requests](CONTRIBUTING.md#features)
* [Pull requests](CONTRIBUTING.md#pull-requests)
## Community
Keep track of development and community news.
* Follow [@EiffelWeb](https://twitter.com/EiffelWeb) on Twitter
* [Forum](https://groups.google.com/forum/#!forum/eiffel-web-framework) on Google groups.
* Follow our [page](https://plus.google.com/u/0/110650349519032194479) and [community](https://plus.google.com/communities/110457383244374256721) on Google+
* Have a question that's not a feature request or bug report? [Ask on the mailing list](http://groups.google.com/group/eiffel-web-framework)
For more information please have a look at the related wiki:
* https://github.com/EiffelWebFramework/EWF/wiki

View File

@@ -29,7 +29,6 @@
<target name="_build_tpl_" >
<argument name="_target_name" />
<geant target="${_target_name}" dir="cURL" file="build.eant" reuse_variables="true" />
</target>
</project>

View File

@@ -0,0 +1,82 @@
note
description: "Summary description for {TCP_STREAM_SOCKET}."
date: "$Date: 2015-02-16 19:53:13 +0100 (lun., 16 févr. 2015) $"
revision: "$Revision: 96642 $"
class
TCP_STREAM_SOCKET
inherit
NETWORK_STREAM_SOCKET
redefine
make
end
create
make_server_by_address_and_port,
make_server_by_port
create {NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
feature {NONE} -- Initialization
make
-- Create a network stream socket.
do
Precursor
set_reuse_address
end
make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
-- Create server socket on `an_address' and `a_port'.
require
valid_port: a_port >= 0
do
make
create address.make_from_address_and_port (an_address, a_port)
bind
end
feature -- Basic operation
send_message (a_msg: STRING)
local
a_package : PACKET
a_data : MANAGED_POINTER
c_string : C_STRING
do
create c_string.make (a_msg)
create a_data.make_from_pointer (c_string.item, a_msg.count + 1)
create a_package.make_from_managed_pointer (a_data)
send (a_package, 1)
end
feature -- Output
put_readable_string_8 (s: READABLE_STRING_8)
-- Write readable string `s' to socket.
local
ext: C_STRING
do
create ext.make (s)
put_managed_pointer (ext.managed_data, 0, s.count)
end
feature -- Status report
try_ready_for_reading: BOOLEAN
-- Is data available for reading from the socket right now?
require
socket_exists: exists
local
retval: INTEGER
do
retval := c_select_poll_with_timeout (descriptor, True, 0)
Result := (retval > 0)
end
note
copyright: "2011-2015, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -17,7 +17,8 @@ create
make_server_by_port
create {NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
make_from_descriptor_and_address,
make_empty
feature {NONE} -- Initialization
@@ -77,6 +78,6 @@ feature -- Status report
end
note
copyright: "2011-2011, Javier Velilla and others"
copyright: "2011-2015, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="nino" uuid="32C1D67D-33DE-4F1E-864B-D45388F2E3E6" library_target="nino">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-12-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-12-0 http://www.eiffel.com/developers/xml/configuration-1-12-0.xsd" name="nino" uuid="32C1D67D-33DE-4F1E-864B-D45388F2E3E6" library_target="nino">
<target name="nino">
<root all_classes="true"/>
<file_rule>
@@ -8,13 +8,28 @@
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" is_attached_by_default="true" void_safety="all">
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
<cluster name="nino" location=".\library\" recursive="true"/>
<cluster name="nino" location=".\library\" recursive="true">
<file_rule>
<exclude>spec</exclude>
</file_rule>
<file_rule>
<exclude>tcp_stream_socket.e</exclude>
<condition>
<version type="compiler" max="15.01.9.6506"/>
</condition>
</file_rule>
</cluster>
<cluster name="spec_before_15_01" location=".\library\spec\before_15_01\" recursive="true">
<condition>
<version type="compiler" max="15.01.9.6506"/>
</condition>
</cluster>
</target>
</system>

View File

@@ -15,6 +15,21 @@
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
<cluster name="nino" location=".\library\" recursive="true"/>
<cluster name="nino" location=".\library\" recursive="true">
<file_rule>
<exclude>spec</exclude>
</file_rule>
<file_rule>
<exclude>tcp_stream_socket.e</exclude>
<condition>
<version type="compiler" max="15.01.9.6506"/>
</condition>
</file_rule>
</cluster>
<cluster name="spec_before_15_01" location=".\library\spec\before_15_01\" recursive="true">
<condition>
<version type="compiler" max="15.01.9.6506"/>
</condition>
</cluster>
</target>
</system>

View File

@@ -1 +0,0 @@

View File

@@ -0,0 +1,10 @@
# Set default behaviour, in case users don't have core.autocrlf set.
# * text=auto
# Explicitly declare text files we want to always be normalized and converted
# to native line endings on checkout.
*.e text
*.ecf text
*.bat text
*.json text
*.txt text

View File

@@ -1,2 +1,2 @@
*.swp
EIFGENs
EIFGENs/

View File

@@ -1,10 +1,12 @@
History file for EJSON
History file for EJSON
======================
team: ""
date: "2011-07-06"
revision: "0.3.0"
WARNING: THIS FILE IS NOT UP TO DATE
+++++++++++++++++++++Important Changes since 0.2.0 version++++++++++++++++++++++++++++++++++++++++++++++

View File

@@ -1,4 +1,5 @@
Copyright (c) 2010 Javier Velilla and others, http://ejson.origo.ethz.ch
Copyright (c) 2010-2014 Javier Velilla, Jocelyn Fiat and others,
https://github.com/eiffelhub/json .
Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@@ -1,21 +1,26 @@
Readme file for eJSON
=====================
team: "Javier Velilla,Jocelyn Fiat, Paul Cohen"
date: "$Date$"
revision: "$Revision$"
team: "Javier Velilla, Jocelyn Fiat"
previous contributors: "Paul Cohen"
date: "2014-nov-17"
1. Introduction
---------------
eJSON stands for Eiffel JSON library and is a small Eiffel library for dealing
with the JSON format. The objective of the library is to provide two basic
features Eiffel2JSON and JSON2Eiffel.
with the JSON format. This library provides a JSON parser and visitors,
including a pretty printer.
The converters part is now obsolete and not recommended (remember: the
objective of converters were to provide two basic features Eiffel2JSON and
JSON2Eiffel). There will be a new design for converters as a standalone
library on top of Current json library.
2. Legal stuff
--------------
eJSON is copyrighted by the author Javier Velilla and others. It is licensed
eJSON is copyrighted by the author Javier Velilla, Jocelyn Fiat and others. It is licensed
under the MIT License. See the file license.txt in the same directory as this
readme file.
@@ -46,11 +51,9 @@ Currently the only documentation on eJSON is available at:
EJSON requires that you have:
1. Gobo 3.9 installed or later
2. One of the following compiler combinations installed:
* ISE Eiffel 6.5 or later.
1. One of the following compiler combinations installed:
* ISE Eiffel 13.11 or later.
* gec [try to test]
* tecomp [try to test]
eJSON probably works fine with other versions of the above compilers.
There are no known platform dependencies (Windows, Linux).
@@ -58,6 +61,8 @@ There are no known platform dependencies (Windows, Linux).
To install eJSON simply extract the ejson-X.Y.Z.zip file to some appropriate
place on your hard disk. There are no requirements on environment variables or
registry variables.
Note eJSON is also delivered within EiffelStudio release, under
$ISE_LIBRARY/contrib/library/text/parser/json
To verify that everything works you should compile the example programs and/or
the test program.
@@ -70,18 +75,18 @@ installation.
Directory Description
--------- -----------
doc Contains the eJSON.pdf documentation file.
examples Contains the two example programs.
ejson Contains the actual eJSON library classes.
test Contains a test program for eJSON.
doc Contains documentation file.
examples Contains example codes.
library Contains the actual eJSON library classes.
test Contains test suite for eJSON.
7. Contacting the Team
----------------------
Contact the team:
https://github.com/eiffelhub/json/issues
Javier Velilla «javier.hector@gmail.com»
Paul Cohen «paco@seibostudios.se»
Jocelyn Fiat «jfiat@eiffel.com»
8. Releases
@@ -92,6 +97,16 @@ history.txt.
Version Date Description
------- ---- -----------
0.6.0 2014-11-17 Fixed various issue with parsing string (such as \t and related),
Implemented escaping of slash '/' only in case of '</' to avoid
potential issue with javascript and </script>
Many feature renaming to match Eiffel style and naming convention,
kept previous feature as obsolete.
Restructured the library to make easy extraction of "converter"
classes if needed in the future.
Marked converters classes as obsolete.
0.5.0 2013-11-dd Added JSON_ITERATOR, simplified JSON_OBJECT
0.4.0 2012-12-12 Updated documentation URI
0.3.0 2011-07-06 JSON Factory Converters
0.2.0 2010-02-07 Adapted to EiffelStudio 6.4 or later, supports void-safety
0.1.0 2010-02-07 First release, Adapted to SmartEiffel 1.2r7 and EiffelStudio 6.2 or previous

View File

@@ -0,0 +1,295 @@
== Preface ==
This document is a living document! As always read and try out the code to understand what's really going on.
=== About the project ===
The eJSON project was started by Javier Velilla in 2008. The aim was simply to
provide JSON support to Eiffel programmers. A couple of other people have been
involved to various extent since the start; Berend de Boer, Jocelyn Fiat and
Manu Stapf. In 2009 Paul Cohen joined the project as an active developer and
later Jocelyn Fiat.
The current active maintainers:
- Javier Velilla
- Jocelyn Fiat
The formal name of the project is “eJSON”.
For questions regarding eJSON please contact
- <javier.hector at gmail.com>
- <jfiat at eiffel.com>
- or directly on [https://github.com/eiffelhub/json/issues]
=== Current version and status ===
The latest release is 0.6.0. eJSON has been improved and cleaned.
The converters are not obsolete.
== Introduction ==
=== What is JSON? ===
JSON (JavaScript Object Notation) is a lightweight computer data interchange format. It is a text-based, human-readable format for representing simple data structures and associative arrays (called objects). See the [http://en.wikipedia.org/wiki/JSON Wikipedia article on JSON], [http://www.json.org www.json.org] and [http://www.json.com www.json.com] for more information.
The JSON format is specified in [http://www.ietf.org/rfc/rfc4627.txt IETF RFC 4627] by Douglas Crockford. The official [http://www.iana.org/assignments/media-types Internet MIME media type] for JSON is "application/json". The recommended file name extension for JSON files is ".json".
=== Advantages ===
1. Lightweight data-interchange format.
2. Easy for humans to read and write.
3. Enables easy integration with AJAX/JavaScript web applications. See the article [http://www.developer.com/lang/jscript/article.php/3596836 Speeding Up AJAX with JSON] for a good short discussion on this subject.
4. JSON data structures translate with ease into the native data structures universal to almost all programming languages used today.
=== Use in Eiffel applications ===
JSON can be used as a general serialization format for Eiffel objects. As such it could be used as a:
* Data representation format in REST-based web service applications written in Eiffel.
* Serialization format for Eiffel objects in persistence solutions.
* File format for configuration files in Eiffel systems.
=== Prerequisites ===
eJSON works today with EiffelStudio 13.11
There is an optional extension that requires the latest snapshot of the Gobo Eiffel libraries (a working snapshot is distributed with EiffelStudio). The depencencies on Gobo are on Gobo's unicode
and regex libraries and for some of the extra features in eJSON, on Gobos structure classes DS_HASH_TABLE and DS_LINKED_LIST.
eJSON is intended to work with all ECMA compliant Eiffel compilers.
=== Installation ===
You can either download a given release and install on your machine or you can get the latest snapshot of the code.
To download go to the [http://ejson.origo.ethz.ch/download download page].
To get the latest snapshot of the code do:
: $ git clone https://github.com/eiffelhub/json.git json
*[https://github.com/eiffelhub/json/releases download page]
*[https://github.com/eiffelhub/json github project]
Note that the latest json release is also delivered with EiffelStudio installation under <code>$ISE_LIBRARY/contrib/library/text/parser/json</code>.
=== Cluster and directory layout ===
json/
library/ (Root directory for eJSON library classes)
kernel/ (All classes in this cluster should eventually only depend on ECMA Eiffel and FreeELKS).
json_array.e
json_boolean.e
json_null.e
json_number.e
json_object.e
json_string.e
json_value.e
parser/
json_parser.e
json_parser_access.e
json_reader.e
json_tokens.e
utility/
file/
json_file_reader.e
visitor/
json_visitor.e
json_iterator.e
json_pretty_string_visitor.e
print_json_visitor.e
converters/ (JSON core converter classes !OBSOLETE!)
json_converter.e
json_hash_table_converter.e
json_list_converter.e
json_linked_list_converter.e
json_arrayed_list_converter.e
support/
ejson.e
shared_ejson.e
gobo_converters/ (JSON core converter classes support for GOBO !OBSOLETE!)
converters/
json_ds_hash_table_converter.e
json_ds_linked_list_converter.e
shared_gobo_ejson.e
test/ (Contains autotest suite)
autotest/ (AutoTest based unit test).
examples/ (Example code)
=== Future development ===
Here is a list of suggestions for future development of eJSON.
* Ongoing: Provide a JSON_FACTORY class for easy conversion between arbitrary JSON and Eiffel values.
* Ongoing: Provide a mechanism for users to add custom converters between JSON values and user space Eiffel classes.
* Ongoing: Implement a full test framework for eJSON.
* Suggestion: Investigate performance and improve it if neccessary.
* Suggestion: Support JSON references. See [http://www.json.com/2007/10/19/json-referencing-proposal-and-library JSON Referencing Proposal and Library] and [http://www.sitepen.com/blog/2008/06/17/json-referencing-in-dojo JSON referencing in Dojo] for more information.
* Suggestion: Support JSON path. See [http://goessner.net/articles/JsonPath JSONPath - XPath for JSON] for more information.
* Suggestion: Support JSON schema validation. See [http://json-schema.org JSON Schema Proposal] for more information.
* Suggestion: Support RDF JSON serialization. See [http://n2.talis.com/wiki/RDF_JSON_Specification RDF JSON Specification] for more information.
* Suggestion: Add support to JSON classes for conversion from Eiffel manifest values. So one can write things like:
== A simple example ==
There are two basic approaches to using eJSON; either you use the basic JSON_VALUE classes, converting to and from JSON values to corresponding Eiffel instances or you use the high level eJSON interface class SHARED_EJSON. Of course you can use a mix of both approaches if you find it appropriate!
Here is an example of how to create a JSON number value from an INTEGER and then obtain the JSON representation for that value.
simple_example is
local
i: INTEGER
jn: JSON_NUMBER
s: STRING
do
i := 42
create jn.make_integer (i)
s := jn.representation -- s.is_equal ("42")
end
== Mapping of JSON values to Eiffel values ==
=== JSON number ===
JSON numbers are represented by the class JSON_NUMBER. JSON number values can be converted to/from NATURAL_*, INTEGER_* and REAL_64 values. For floating point values REAL_* is used. The complete mapping is as follows:
JSON number -> Eiffel:
* -128 <= n <= +127 -> INTEGER_8
* n can't be represented by INTEGER_8 and -32768 <= n <= +32767 -> INTEGER_16
* n can't be represented by INTEGER_16 and -2147483648 <= n <= +2147483647 -> INTEGER_32
* n can't be represented by INTEGER_32 and -9223372036854775808 <= n <= +9223372036854775807 -> INTEGER_64
* n can't be represented by INTEGER_64 and 9223372036854775808 <= n <= 18446744073709551615 -> NATURAL_64
* n has fractional dot '.' -> REAL_64.
* n -> eJSON exception if number can't be represented by a INTEGER_64, NATURAL_64 or REAL_64.
Eiffel -> JSON number:
* NATURAL_8, NATURAL_16, NATURAL_32, NATURAL_64, NATURAL -> JSON number
* INTEGER_8, INTEGER_16, INTEGER_32, INTEGER_64, INTEGER -> JSON number
* REAL_32, REAL_64, REAL -> JSON number
You can use the following creation routines to create JSON_NUMBER instances:
* JSON_NUMBER.make_integer
* JSON_NUMBER.make_real
* JSON_NUMBER.make_natural
eiffel_to_json_number_representation is
local
i: INTEGER
r: REAL
jn: JSON_NUMBER
do
print ("JSON representation of Eiffel INTEGER: '")
i := 123
create jn.make_integer (i)
print (jn.representation)
print ("'%N")
print ("JSON representation of Eiffel REAL: '")
r := 12.3
create jn.make_real (r)
print (jn.representation)
print ("'%N")
end
The output of the above code will be:
JSON representation of Eiffel INTEGER: '123'
JSON representation of Eiffel REAL: '12.300000190734863'
=== JSON boolean ===
JSON boolean values are represented by the class JSON_BOOLEAN. The JSON boolean value "true" is converted to/from the BOOLEAN value "True" and the JSON boolean value "false is converted to/from the BOOLEAN value "False".
eiffel_to_json_boolean_representation is
local
b: BOOLEAN
jb: JSON_BOOLEAN
do
print ("JSON representation of Eiffel BOOLEAN: '")
b := True
create jb.make (b)
print (jb.representation)
print ("'%N")
print("JSON representation of Eiffel BOOLEAN: '")
b := False
create jb.make (b)
print (jb.representation)
print ("'%N")
end
The output of the above code will be:
JSON representation of Eiffel BOOLEAN: 'true'
JSON representation of Eiffel BOOLEAN: 'false'
=== JSON string ===
JSON strings are represented by the class JSON_STRING. JSON string values can be converted to/from STRING_32, STRING and CHARACTER values. The complete mapping is as follows:
JSON string -> Eiffel:
* All JSON strings -> STRING or STRING_32
Eiffel -> JSON string:
* STRING_32 -> JSON string
* STRING -> JSON string
* CHARACTER -> JSON string
eiffel_to_json_string_representation is
local
s: STRING
js: JSON_STRING
do
print ("JSON representation of Eiffel STRING: '")
s := "JSON rocks!"
create js.make_from_string (s)
print (js.representation)
print ("'%N")
end
The output of the above code will be:
JSON representation of Eiffel STRING: '"JSON rocks!"'
Note: JSON escape unicode characters, as well a other specific characters, to get the unescaped string value, use either 'unescaped_string_8' or 'unescaped_string_32'.
=== JSON null ===
The JSON null value is represented by the class JSON_NULL. The JSON null value can be converted to/from Void.
eiffel_to_json_null_representation is
local
a: ANY
jn: JSON_NULL
do
create jn
print ("JSON representation for JSON null value: '")
print (jn.representation)
print ("'%N")
a := Void
if attached {JSON_NULL} json.value (a) as l_jn then -- json from SHARED_EJSON!
print ("JSON representation of Eiffel Void reference: '")
print (l_jn.representation)
print ("'%N")
end
end
The output of the above code will be:
JSON representation for JSON null value: 'null'
JSON representation of Eiffel Void reference: 'null'
=== JSON array ===
JSON array is represented by the class JSON_ARRAY.
=== JSON object ===
JSON object is represented by the class JSON_OBJECT.
== The eJSON visitor pattern ==
TBD. See examples.
== The eJSON file reader class ==
TBD.

View File

@@ -0,0 +1,83 @@
class
BASIC
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
local
parser: JSON_PARSER
printer: JSON_PRETTY_STRING_VISITOR
s: STRING_32
do
-- Create parser for content `json_content'
create parser.make_with_string (json_content)
-- Parse the content
parser.parse_content
if
parser.is_valid and then
attached parser.parsed_json_value as jv
then
-- Json content is valid, and well parser.
-- and the parsed json value is `jv'
-- Let's access the glossary/title value
if
attached {JSON_OBJECT} jv as j_object and then
attached {JSON_OBJECT} j_object.item ("glossary") as j_glossary and then
attached {JSON_STRING} j_glossary.item ("title") as j_title
then
print ("The glossary title is %"" + j_title.unescaped_string_8 + "%".%N")
else
print ("The glossary title was not found!%N")
end
-- Pretty print the parsed JSON
create s.make_empty
create printer.make (s)
jv.accept (printer)
print ("The JSON formatted using a pretty printer:%N")
print (s)
end
end
feature -- Status
feature -- Access
json_content: STRING = "[
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
]"
feature -- Change
feature {NONE} -- Implementation
invariant
-- invariant_clause: True
end

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="basic" uuid="5156B9EE-0436-42A3-BDA1-74710DF05A35">
<target name="basic">
<root class="BASIC" feature="make"/>
<setting name="console_application" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="json" location="..\..\library\json-safe.ecf" readonly="false"/>
<cluster name="basic" location=".\"/>
</target>
</system>

View File

@@ -5,9 +5,14 @@ note
revision: "$Revision$"
file: "$HeadURL: $"
class JSON_ARRAYED_LIST_CONVERTER
class
JSON_ARRAYED_LIST_CONVERTER
obsolete
"This JSON converter design has issues [Sept/2014]."
inherit
JSON_LIST_CONVERTER
redefine
object
@@ -27,4 +32,7 @@ feature {NONE} -- Factory
create Result.make (nb)
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end -- class JSON_ARRAYED_LIST_CONVERTER

View File

@@ -0,0 +1,44 @@
note
description: "A JSON converter"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
deferred class
JSON_CONVERTER
obsolete
"This JSON converter design has issues [Sept/2014]."
inherit
SHARED_EJSON
feature -- Access
object: ANY
-- Eiffel object
deferred
end
feature -- Conversion
from_json (j: attached like to_json): detachable like object
-- Convert from JSON value.
-- Returns Void if unable to convert
deferred
end
to_json (o: like object): detachable JSON_VALUE
-- Convert to JSON value
deferred
end
invariant
has_eiffel_object: object /= Void -- An empty object must be created at creation time!
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -0,0 +1,88 @@
note
description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]"
author: "Paul Cohen"
date: "$Date: 2014-01-30 15:27:41 +0100 (jeu., 30 janv. 2014) $"
revision: "$Revision: 94128 $"
file: "$HeadURL: $"
class
JSON_HASH_TABLE_CONVERTER
obsolete
"This JSON converter design has issues [Sept/2014]."
inherit
JSON_CONVERTER
create
make
feature {NONE} -- Initialization
make
do
create object.make (0)
end
feature -- Access
object: HASH_TABLE [ANY, HASHABLE]
feature -- Conversion
from_json (j: attached like to_json): like object
do
create Result.make (j.count)
across
j as ic
loop
if attached json.object (ic.item, Void) as l_object then
if attached {HASHABLE} json.object (ic.key, Void) as h then
Result.put (l_object, h)
else
check
key_is_hashable: False
end
end
else
check
object_attached: False
end
end
end
end
to_json (o: like object): detachable JSON_OBJECT
local
js: JSON_STRING
failed: BOOLEAN
do
create Result.make
across
o as c
loop
if attached {JSON_STRING} json.value (c.key) as l_key then
js := l_key
else
if attached {READABLE_STRING_GENERAL} c.key as s_key then
create js.make_from_string_general (s_key)
else
create js.make_from_string (c.key.out)
end
end
if attached json.value (c.item) as jv then
Result.put (jv, js)
else
failed := True
end
end
if failed then
Result := Void
end
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end -- class JSON_HASH_TABLE_CONVERTER

View File

@@ -5,9 +5,14 @@ note
revision: "$Revision$"
file: "$HeadURL: $"
class JSON_LINKED_LIST_CONVERTER
class
JSON_LINKED_LIST_CONVERTER
obsolete
"This JSON converter design has issues [Sept/2014]."
inherit
JSON_LIST_CONVERTER
redefine
object
@@ -27,4 +32,7 @@ feature {NONE} -- Factory
create Result.make
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end -- class JSON_LINKED_LIST_CONVERTER

View File

@@ -0,0 +1,80 @@
note
description: "A JSON converter for LIST [ANY]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
deferred class
JSON_LIST_CONVERTER
obsolete
"This JSON converter design has issues [Sept/2014]."
inherit
JSON_CONVERTER
feature {NONE} -- Initialization
make
do
object := new_object (0)
end
feature -- Access
object: LIST [detachable ANY]
feature {NONE} -- Factory
new_object (nb: INTEGER): like object
deferred
ensure
Result /= Void
end
feature -- Conversion
from_json (j: attached like to_json): detachable like object
local
i: INTEGER
do
Result := new_object (j.count)
from
i := 1
until
i > j.count
loop
Result.extend (json.object (j [i], Void))
i := i + 1
end
end
to_json (o: like object): detachable JSON_ARRAY
local
c: ITERATION_CURSOR [detachable ANY]
failed: BOOLEAN
do
create Result.make (o.count)
from
c := o.new_cursor
until
c.after
loop
if attached json.value (c.item) as jv then
Result.add (jv)
else
failed := True
end
c.forth
end
if failed then
Result := Void
end
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end -- class JSON_ARRAYED_LIST_CONVERTER

View File

@@ -5,9 +5,14 @@ note
revision: "$Revision$"
file: "$HeadURL: $"
class EJSON
class
EJSON
obsolete
"This JSON converter design has issues [Sept/2014]."
inherit
EXCEPTIONS
feature -- Access
@@ -25,7 +30,7 @@ feature -- Access
if an_object = Void then
create {JSON_NULL} Result
elseif attached {BOOLEAN} an_object as b then
create {JSON_BOOLEAN} Result.make_boolean (b)
create {JSON_BOOLEAN} Result.make (b)
elseif attached {INTEGER_8} an_object as i8 then
create {JSON_NUMBER} Result.make_integer (i8)
elseif attached {INTEGER_16} an_object as i16 then
@@ -47,7 +52,7 @@ feature -- Access
elseif attached {REAL_64} an_object as r64 then
create {JSON_NUMBER} Result.make_real (r64)
elseif attached {ARRAY [detachable ANY]} an_object as a then
create ja.make_array
create ja.make (a.count)
from
i := a.lower
until
@@ -56,22 +61,22 @@ feature -- Access
if attached value (a @ i) as v then
ja.add (v)
else
check value_attached: False end
check
value_attached: False
end
end
i := i + 1
end
Result := ja
elseif attached {CHARACTER_8} an_object as c8 then
create {JSON_STRING} Result.make_json (c8.out)
create {JSON_STRING} Result.make_from_string (c8.out)
elseif attached {CHARACTER_32} an_object as c32 then
create {JSON_STRING} Result.make_json (c32.out)
create {JSON_STRING} Result.make_from_string_32 (create {STRING_32}.make_filled (c32, 1))
elseif attached {STRING_8} an_object as s8 then
create {JSON_STRING} Result.make_json (s8)
create {JSON_STRING} Result.make_from_string (s8)
elseif attached {STRING_32} an_object as s32 then
create {JSON_STRING} Result.make_json_from_string_32 (s32)
create {JSON_STRING} Result.make_from_string_32 (s32)
end
if Result = Void then
-- Now check the converters
if an_object /= Void and then attached converter_for (an_object) as jc then
@@ -160,12 +165,10 @@ feature -- Access
-- "eJSON exception" if unable to convert value.
require
json_not_void: json /= Void
local
jv: detachable JSON_VALUE
do
json_parser.set_representation (json)
jv := json_parser.parse
if jv /= Void then
json_parser.parse_content
if json_parser.is_valid and then attached json_parser.parsed_json_value as jv then
Result := object (jv, base_class)
end
end
@@ -190,8 +193,8 @@ feature -- Access
js_key, js_value: JSON_STRING
do
create Result.make
create js_key.make_json ("$ref")
create js_value.make_json (s)
create js_key.make_from_string ("$ref")
create js_value.make_from_string (s)
Result.put (js_value, js_key)
end
@@ -205,7 +208,7 @@ feature -- Access
local
c: ITERATION_CURSOR [STRING]
do
create Result.make_array
create Result.make (l.count)
from
c := l.new_cursor
until
@@ -262,7 +265,10 @@ feature {NONE} -- Implementation (JSON parser)
json_parser: JSON_PARSER
once
create Result.make_parser ("")
create Result.make_with_string ("{}")
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end -- class EJSON

View File

@@ -0,0 +1,43 @@
note
description: "[
Shared factory class for creating JSON objects. Maps JSON
objects to ELKS HASH_TABLEs and JSON arrays to ELKS
LINKED_LISTs. Use non-conforming inheritance from this
class to ensure that your classes share the same
JSON_FACTORY instance.
]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision: 89185 $"
file: "$HeadURL: $"
class
SHARED_EJSON
obsolete
"This JSON converter design has issues [Sept/2014]."
feature -- Access
json: EJSON
-- A shared EJSON instance with default converters for
--LINKED_LIST [ANY] and HASH_TABLE [ANY, HASHABLE]
local
jalc: JSON_ARRAYED_LIST_CONVERTER
jllc: JSON_LINKED_LIST_CONVERTER
jhtc: JSON_HASH_TABLE_CONVERTER
once
create Result
create jalc.make
Result.add_converter (jalc)
create jllc.make
Result.add_converter (jllc)
create jhtc.make
Result.add_converter (jhtc)
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end -- class SHARED_EJSON

View File

@@ -1,38 +0,0 @@
note
description: "Objects that ..."
author: ""
date: "$Date$"
revision: "$Revision$"
class
JSON_FILE_READER
feature -- Access
read_json_from (a_path: STRING): detachable STRING
local
l_file: PLAIN_TEXT_FILE
template_content: STRING
l_last_string: detachable STRING
do
create l_file.make (a_path)
-- We perform several checks until we make a real attempt to open the file.
if not l_file.exists then
print ("error: '" + a_path + "' does not exist%N")
else
if not l_file.is_readable then
print ("error: '" + a_path + "' is not readable.%N")
else
l_file.open_read
create template_content.make_empty
l_file.read_stream (l_file.count)
l_last_string := l_file.last_string
check l_last_string /= Void end -- implied by postcondition of `l_file.read_stream'
template_content.append (l_last_string.string)
Result := template_content
l_file.close
end
end
end
end

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json" uuid="4E21C3BD-7951-4C6E-A673-431E762D7414" library_target="json">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-12-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-12-0 http://www.eiffel.com/developers/xml/configuration-1-12-0.xsd" name="json" uuid="4E21C3BD-7951-4C6E-A673-431E762D7414" library_target="json">
<target name="json">
<root all_classes="true"/>
<file_rule>
@@ -9,20 +9,13 @@
</file_rule>
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard" namespace="EJSON.Library">
<assertions/>
<warning name="export_class_missing" enabled="false"/>
<warning name="old_verbatim_strings" enabled="false"/>
<warning name="syntax" enabled="false"/>
<warning name="vjrv" enabled="false"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf" readonly="true"/>
<cluster name="json" location=".\" recursive="true">
<file_rule>
<exclude>^/gobo$</exclude>
<exclude>^/kernel$</exclude>
<exclude>^/extras$</exclude>
</file_rule>
<cluster name="kernel" location=".\kernel\" recursive="true"/>
<cluster name="extras" location=".\extras\" recursive="true"/>
<cluster name="json" location=".\">
<cluster name="json_kernel" location=".\kernel\" recursive="true"/>
<cluster name="json_parser" location=".\parser\" recursive="true"/>
<cluster name="json_utility" location=".\utility\" recursive="true"/>
</cluster>
<cluster name="json_converter" location=".\converter\" recursive="true"/>
</target>
</system>

View File

@@ -9,20 +9,13 @@
</file_rule>
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
<assertions/>
<warning name="export_class_missing" enabled="false"/>
<warning name="old_verbatim_strings" enabled="false"/>
<warning name="syntax" enabled="false"/>
<warning name="vjrv" enabled="false"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
<cluster name="json" location=".\" recursive="true">
<file_rule>
<exclude>^/gobo$</exclude>
<exclude>^/kernel$</exclude>
<exclude>^/extras$</exclude>
</file_rule>
<cluster name="kernel" location=".\kernel\" recursive="true"/>
<cluster name="extras" location=".\extras\" recursive="true"/>
<cluster name="json" location=".\" >
<cluster name="json_kernel" location=".\kernel" recursive="true"/>
<cluster name="json_parser" location=".\parser" recursive="true"/>
<cluster name="json_utility" location=".\utility" recursive="true"/>
</cluster>
<cluster name="json_converter" location=".\converter" recursive="true"/>
</target>
</system>

View File

@@ -12,6 +12,6 @@
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
<library name="json" location="json.ecf" readonly="true"/>
<library name="gobo_structure" location="$ISE_LIBRARY\library\gobo\gobo_structure.ecf"/>
<cluster name="json_gobo" location=".\gobo" recursive="true" />
<cluster name="json_gobo_converter" location=".\gobo_converter" recursive="true" />
</target>
</system>

View File

@@ -1,36 +0,0 @@
note
description: "A JSON converter"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
deferred class JSON_CONVERTER
inherit
SHARED_EJSON
feature -- Access
object: ANY
-- Eiffel object
deferred
end
feature -- Conversion
from_json (j: attached like to_json): detachable like object
-- Convert from JSON value.
-- Returns Void if unable to convert
deferred
end
to_json (o: like object): detachable JSON_VALUE
-- Convert to JSON value
deferred
end
invariant
has_eiffel_object: object /= Void -- An empty object must be created at creation time!
end

View File

@@ -1,92 +0,0 @@
note
description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
class JSON_HASH_TABLE_CONVERTER
inherit
JSON_CONVERTER
create
make
feature {NONE} -- Initialization
make
do
create object.make (0)
end
feature -- Access
object: HASH_TABLE [ANY, HASHABLE]
feature -- Conversion
from_json (j: attached like to_json): like object
local
keys: ARRAY [JSON_STRING]
i: INTEGER
h: detachable HASHABLE
jv: detachable JSON_VALUE
a: detachable ANY
do
keys := j.current_keys
create Result.make (keys.count)
from
i := 1
until
i > keys.count
loop
h ?= json.object (keys [i], Void)
check h /= Void end
jv := j.item (keys [i])
if jv /= Void then
a := json.object (jv, Void)
if a /= Void then
Result.put (a, h)
else
check a_attached: a /= Void end
end
else
check j_has_item: False end
end
i := i + 1
end
end
to_json (o: like object): detachable JSON_OBJECT
local
c: HASH_TABLE_ITERATION_CURSOR [ANY, HASHABLE]
js: JSON_STRING
jv: detachable JSON_VALUE
failed: BOOLEAN
do
create Result.make
from
c := o.new_cursor
until
c.after
loop
if attached {JSON_STRING} json.value (c.key) as l_key then
js := l_key
else
create js.make_json (c.key.out)
end
jv := json.value (c.item)
if jv /= Void then
Result.put (jv, js)
else
failed := True
end
c.forth
end
if failed then
Result := Void
end
end
end -- class JSON_HASH_TABLE_CONVERTER

View File

@@ -1,74 +0,0 @@
note
description: "A JSON converter for LIST [ANY]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision$"
file: "$HeadURL: $"
deferred class JSON_LIST_CONVERTER
inherit
JSON_CONVERTER
feature {NONE} -- Initialization
make
do
object := new_object (0)
end
feature -- Access
object: LIST [detachable ANY]
feature {NONE} -- Factory
new_object (nb: INTEGER): like object
deferred
ensure
Result /= Void
end
feature -- Conversion
from_json (j: attached like to_json): detachable like object
local
i: INTEGER
do
Result := new_object (j.count)
from
i := 1
until
i > j.count
loop
Result.extend (json.object (j [i], Void))
i := i + 1
end
end
to_json (o: like object): detachable JSON_ARRAY
local
c: ITERATION_CURSOR [detachable ANY]
jv: detachable JSON_VALUE
failed: BOOLEAN
do
create Result.make_array
from
c := o.new_cursor
until
c.after
loop
jv := json.value (c.item)
if jv /= Void then
Result.add (jv)
else
failed := True
end
c.forth
end
if failed then
Result := Void
end
end
end -- class JSON_ARRAYED_LIST_CONVERTER

View File

@@ -7,28 +7,45 @@ note
[]
[elements]
]"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
author: "$Author$"
date: "$date$"
revision: "$Revision$"
class
JSON_ARRAY
inherit
JSON_VALUE
ITERABLE [JSON_VALUE]
DEBUG_OUTPUT
create
make, make_empty,
make_array
feature {NONE} -- Initialization
make (nb: INTEGER)
-- Initialize JSON array with capacity of `nb' items.
do
create items.make (nb)
end
make_empty
-- Initialize empty JSON array.
do
make (0)
end
make_array
-- Initialize JSON Array
obsolete
"Use `make' Sept/2014"
do
create values.make (10)
make (10)
end
feature -- Access
@@ -38,24 +55,19 @@ feature -- Access
require
is_valid_index: valid_index (i)
do
Result := values.i_th (i)
Result := items.i_th (i)
end
representation: STRING
local
i: INTEGER
do
Result := "["
from
i := 1
until
i > count
across
items as ic
loop
Result.append (i_th (i).representation)
i := i + 1
if i <= count then
if Result.count > 1 then
Result.append_character (',')
end
Result.append (ic.item.representation)
end
Result.append_character (']')
end
@@ -69,12 +81,20 @@ feature -- Visitor pattern
a_visitor.visit_json_array (Current)
end
feature -- Access
new_cursor: ITERATION_CURSOR [JSON_VALUE]
-- Fresh cursor associated with current structure
do
Result := items.new_cursor
end
feature -- Mesurement
count: INTEGER
-- Number of items.
do
Result := values.count
Result := items.count
end
feature -- Status report
@@ -87,39 +107,67 @@ feature -- Status report
feature -- Change Element
add (value: JSON_VALUE)
put_front (v: JSON_VALUE)
require
value_not_null: value /= void
v_not_void: v /= Void
do
values.extend (value)
items.put_front (v)
ensure
has_new_value: old values.count + 1 = values.count and
values.has (value)
has_new_value: old items.count + 1 = items.count and items.first = v
end
add, extend (v: JSON_VALUE)
require
v_not_void: v /= Void
do
items.extend (v)
ensure
has_new_value: old items.count + 1 = items.count and items.has (v)
end
prune_all (v: JSON_VALUE)
-- Remove all occurrences of `v'.
require
v_not_void: v /= Void
do
items.prune_all (v)
ensure
not_has_new_value: not items.has (v)
end
wipe_out
-- Remove all items.
do
items.wipe_out
end
feature -- Report
hash_code: INTEGER
-- Hash code value
local
l_started: BOOLEAN
do
from
values.start
Result := values.item.hash_code
until
values.off
across
items as ic
loop
Result:= ((Result \\ 8388593) |<< 8) + values.item.hash_code
values.forth
if l_started then
Result := ((Result \\ 8388593) |<< 8) + ic.item.hash_code
else
Result := ic.item.hash_code
l_started := True
end
Result := Result \\ values.count
end
Result := Result \\ items.count
end
feature -- Conversion
array_representation: ARRAYED_LIST [JSON_VALUE]
-- Representation as a sequences of values
-- Representation as a sequences of values.
-- be careful, modifying the return object may have impact on the original JSON_ARRAY object.
do
Result := values
Result := items
end
feature -- Status report
@@ -127,15 +175,18 @@ feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
Result := count.out
Result := count.out + " item(s)"
end
feature {NONE} -- Implementation
values: ARRAYED_LIST [JSON_VALUE]
items: ARRAYED_LIST [JSON_VALUE]
-- Value container
invariant
value_not_void: values /= Void
items_not_void: items /= Void
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -1,24 +1,47 @@
note
description: "JSON Truth values"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
description: "JSON Boolean values"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
class
JSON_BOOLEAN
inherit
JSON_VALUE
create
make,
make_true, make_false,
make_boolean
feature {NONE} -- Initialization
make_boolean (an_item: BOOLEAN)
--Initialize.
make (a_value: BOOLEAN)
-- Initialize Current JSON boolean with `a_boolean'.
do
item := an_item
item := a_value
end
make_true
-- Initialize Current JSON boolean with True.
do
make (True)
end
make_false
-- Initialize Current JSON boolean with False.
do
make (False)
end
make_boolean (a_item: BOOLEAN)
-- Initialize.
obsolete
"Use `make' Sept/2014"
do
make (a_item)
end
feature -- Access
@@ -58,4 +81,7 @@ feature -- Status report
Result := item.out
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -8,6 +8,7 @@ class
JSON_NULL
inherit
JSON_VALUE
feature --Access
@@ -44,4 +45,7 @@ feature {NONE}-- Implementation
null_value: STRING = "null"
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -1,24 +1,22 @@
note
description: "JSON Numbers, octal and hexadecimal formats are not used."
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
class
JSON_NUMBER
inherit
JSON_VALUE
redefine
is_equal
end
create
make_integer,
make_natural,
make_real
make_integer, make_natural, make_real
feature {NONE} -- initialization
@@ -26,21 +24,21 @@ feature {NONE} -- initialization
-- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'.
do
item := an_argument.out
numeric_type := INTEGER_TYPE
numeric_type := integer_type
end
make_natural (an_argument: NATURAL_64)
-- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'.
do
item := an_argument.out
numeric_type := NATURAL_TYPE
numeric_type := natural_type
end
make_real (an_argument: DOUBLE)
make_real (an_argument: REAL_64)
-- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'.
do
item := an_argument.out
numeric_type := DOUBLE_TYPE
numeric_type := double_type
end
feature -- Access
@@ -48,6 +46,9 @@ feature -- Access
item: STRING
-- Content
numeric_type: INTEGER
-- Type of number (integer, natural or real).
hash_code: INTEGER
--Hash code value
do
@@ -59,6 +60,52 @@ feature -- Access
Result := item
end
feature -- Conversion
integer_64_item: INTEGER_64
-- Associated integer value.
require
is_integer: is_integer
do
Result := item.to_integer_64
end
natural_64_item: NATURAL_64
-- Associated natural value.
require
is_natural: is_natural
do
Result := item.to_natural_64
end
double_item, real_64_item: REAL_64
-- Associated real value.
require
is_real: is_real
do
Result := item.to_real_64
end
feature -- Status report
is_integer: BOOLEAN
-- Is Current an integer number?
do
Result := numeric_type = integer_type
end
is_natural: BOOLEAN
-- Is Current a natural number?
do
Result := numeric_type = natural_type
end
is_double, is_real: BOOLEAN
-- Is Current a real number?
do
Result := numeric_type = real_type
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
@@ -87,13 +134,16 @@ feature -- Status report
feature -- Implementation
INTEGER_TYPE: INTEGER = 1
DOUBLE_TYPE: INTEGER = 2
NATURAL_TYPE: INTEGER = 3
integer_type: INTEGER = 1
numeric_type: INTEGER
double_type, real_type: INTEGER = 2
natural_type: INTEGER = 3
invariant
item_not_void: item /= Void
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -1,114 +1,251 @@
note
description: "[
An JSON_OBJECT represent an object in JSON.
An object is an unordered set of name/value pairs
Examples:
object
{}
{"key","value"}
{"key": value}
{"key": "value"}
]"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
class
JSON_OBJECT
inherit
JSON_VALUE
TABLE_ITERABLE [JSON_VALUE, JSON_STRING]
DEBUG_OUTPUT
create
make
make_empty, make_with_capacity, make
feature {NONE} -- Initialization
make
-- Initialize
make_with_capacity (nb: INTEGER)
-- Initialize with a capacity of `nb' items.
do
create object.make (10)
create items.make (nb)
end
make_empty
-- Initialize as empty object.
do
make_with_capacity (0)
end
make
-- Initialize with default capacity.
do
make_with_capacity (3)
end
feature -- Change Element
put (value: detachable JSON_VALUE; key: JSON_STRING)
-- Assuming there is no item of key `key',
-- insert `value' with `key'.
put (a_value: detachable JSON_VALUE; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
require
key_not_present: not has_key (key)
local
l_value: like value
a_key_not_present: not has_key (a_key)
do
l_value := value
if l_value = Void then
create {JSON_NULL} l_value
if a_value = Void then
items.extend (create {JSON_NULL}, a_key)
else
items.extend (a_value, a_key)
end
object.extend (l_value, key)
end
replace (value: detachable JSON_VALUE; key: JSON_STRING)
-- Assuming there is no item of key `key',
-- insert `value' with `key'.
put_string (a_value: READABLE_STRING_GENERAL; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
require
key_not_present: not has_key (a_key)
local
l_value: like value
l_value: JSON_STRING
do
l_value := value
if l_value = Void then
create {JSON_NULL} l_value
if attached {READABLE_STRING_8} a_value as s then
create l_value.make_from_string (s)
else
create l_value.make_from_string_32 (a_value.as_string_32)
end
object.force (l_value, key)
put (l_value, a_key)
end
put_integer (a_value: INTEGER_64; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
require
key_not_present: not has_key (a_key)
local
l_value: JSON_NUMBER
do
create l_value.make_integer (a_value)
put (l_value, a_key)
end
put_natural (a_value: NATURAL_64; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
require
key_not_present: not has_key (a_key)
local
l_value: JSON_NUMBER
do
create l_value.make_natural (a_value)
put (l_value, a_key)
end
put_real (a_value: DOUBLE; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
require
key_not_present: not has_key (a_key)
local
l_value: JSON_NUMBER
do
create l_value.make_real (a_value)
put (l_value, a_key)
end
put_boolean (a_value: BOOLEAN; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
require
key_not_present: not has_key (a_key)
local
l_value: JSON_BOOLEAN
do
create l_value.make (a_value)
put (l_value, a_key)
end
replace (a_value: detachable JSON_VALUE; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
do
if a_value = Void then
items.force (create {JSON_NULL}, a_key)
else
items.force (a_value, a_key)
end
end
replace_with_string (a_value: READABLE_STRING_GENERAL; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
local
l_value: JSON_STRING
do
if attached {READABLE_STRING_8} a_value as s then
create l_value.make_from_string (s)
else
create l_value.make_from_string_32 (a_value.as_string_32)
end
replace (l_value, a_key)
end
replace_with_integer (a_value: INTEGER_64; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
local
l_value: JSON_NUMBER
do
create l_value.make_integer (a_value)
replace (l_value, a_key)
end
replace_with_with_natural (a_value: NATURAL_64; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
local
l_value: JSON_NUMBER
do
create l_value.make_natural (a_value)
replace (l_value, a_key)
end
replace_with_real (a_value: DOUBLE; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
local
l_value: JSON_NUMBER
do
create l_value.make_real (a_value)
replace (l_value, a_key)
end
replace_with_boolean (a_value: BOOLEAN; a_key: JSON_STRING)
-- Assuming there is no item of key `a_key',
-- insert `a_value' with `a_key'.
local
l_value: JSON_BOOLEAN
do
create l_value.make (a_value)
replace (l_value, a_key)
end
remove (a_key: JSON_STRING)
-- Remove item indexed by `a_key' if any.
do
items.remove (a_key)
end
wipe_out
-- Reset all items to default values; reset status.
do
items.wipe_out
end
feature -- Status report
has_key (a_key: JSON_STRING): BOOLEAN
-- has the JSON_OBJECT contains a specific key `a_key'.
do
Result := items.has (a_key)
end
has_item (a_value: JSON_VALUE): BOOLEAN
-- has the JSON_OBJECT contain a specfic item `a_value'
do
Result := items.has_item (a_value)
end
feature -- Access
has_key (key: JSON_STRING): BOOLEAN
-- has the JSON_OBJECT contains a specific key 'key'.
item (a_key: JSON_STRING): detachable JSON_VALUE
-- the json_value associated with a key `a_key'.
do
Result := object.has (key)
end
has_item (value: JSON_VALUE): BOOLEAN
-- has the JSON_OBJECT contain a specfic item 'value'
do
Result := object.has_item (value)
end
item (key: JSON_STRING): detachable JSON_VALUE
-- the json_value associated with a key.
do
Result := object.item (key)
Result := items.item (a_key)
end
current_keys: ARRAY [JSON_STRING]
-- array containing actually used keys
-- Array containing actually used keys.
do
Result := object.current_keys
Result := items.current_keys
end
representation: STRING
local
t: HASH_TABLE [JSON_VALUE, JSON_STRING]
-- <Precursor>
do
Result := "{"
from
t := map_representation
t.start
until
t.after
create Result.make (2)
Result.append_character ('{')
across
items as ic
loop
Result.append (t.key_for_iteration.representation)
Result.append (":")
Result.append (t.item_for_iteration.representation)
t.forth
if not t.after then
if Result.count > 1 then
Result.append_character (',')
end
Result.append (ic.key.representation)
Result.append_character (':')
Result.append (ic.item.representation)
end
Result.append_character ('}')
end
@@ -116,9 +253,9 @@ feature -- Access
feature -- Mesurement
count: INTEGER
-- Number of field
-- Number of field.
do
Result := object.count
Result := items.count
end
feature -- Access
@@ -126,7 +263,7 @@ feature -- Access
new_cursor: TABLE_ITERATION_CURSOR [JSON_VALUE, JSON_STRING]
-- Fresh cursor associated with current structure
do
Result := object.new_cursor
Result := items.new_cursor
end
feature -- Status report
@@ -134,7 +271,7 @@ feature -- Status report
is_empty: BOOLEAN
-- Is empty object?
do
Result := object.is_empty
Result := items.is_empty
end
feature -- Visitor pattern
@@ -151,7 +288,7 @@ feature -- Conversion
map_representation: HASH_TABLE [JSON_VALUE, JSON_STRING]
-- A representation that maps keys to values
do
Result := object
Result := items
end
feature -- Report
@@ -160,13 +297,13 @@ feature -- Report
-- Hash code value
do
from
object.start
Result := object.out.hash_code
items.start
Result := items.out.hash_code
until
object.off
items.off
loop
Result := ((Result \\ 8388593) |<< 8) + object.item_for_iteration.hash_code
object.forth
Result := ((Result \\ 8388593) |<< 8) + items.item_for_iteration.hash_code
items.forth
end
-- Ensure it is a positive value.
Result := Result.hash_code
@@ -177,15 +314,18 @@ feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
Result := object.count.out
Result := count.out + "item(s)"
end
feature {NONE} -- Implementation
object: HASH_TABLE [JSON_VALUE, JSON_STRING]
items: HASH_TABLE [JSON_VALUE, JSON_STRING]
-- Value container
invariant
object_not_null: object /= Void
items_not_void: items /= Void
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -1,39 +1,92 @@
note
description: "[
A JSON_STRING represent a string in JSON.
A string is a collection of zero or more Unicodes characters, wrapped in double
quotes, using blackslash espaces.
]"
author: "Javier Velilla"
date: "2008/08/24"
revision: "Revision 0.1"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
class
JSON_STRING
inherit
JSON_VALUE
redefine
is_equal
end
create
make_json,
make_json_from_string_32,
make_with_escaped_json
make_from_string, make_from_string_32, make_from_string_general,
make_from_escaped_json_string,
make_with_escaped_json, make_json, make_json_from_string_32
convert
make_json ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
make_json_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32})
make_from_string ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
make_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32}),
make_from_string_general ({READABLE_STRING_GENERAL, STRING_GENERAL, IMMUTABLE_STRING_GENERAL})
feature {NONE} -- Initialization
make_from_string (s: READABLE_STRING_8)
-- Initialize from ascii string `s'.
require
s_not_void: s /= Void
do
make_from_escaped_json_string (escaped_json_string (s))
end
make_from_string_32 (s: READABLE_STRING_32)
-- Initialize from unicode string `s'.
require
s_not_void: s /= Void
do
make_from_escaped_json_string (escaped_json_string (s))
end
make_from_string_general (s: READABLE_STRING_GENERAL)
-- Initialize from string `s'.
require
s_not_void: s /= Void
do
if attached {READABLE_STRING_8} s as s8 then
make_from_string (s8)
else
make_from_string_32 (s.as_string_32)
end
end
make_from_escaped_json_string (a_escaped_string: READABLE_STRING_8)
-- Initialize with `a_escaped_string' already JSON escaped.
require
a_escaped_string_not_void: a_escaped_string /= Void
do
item := a_escaped_string
end
make_with_escaped_json (a_escaped_string: READABLE_STRING_8)
-- Initialize with `a_escaped_string' already JSON escaped.
obsolete
"Use `make_from_escaped_json_string' Sept/2014"
require
a_escaped_string_not_void: a_escaped_string /= Void
do
make_from_escaped_json_string (a_escaped_string)
end
make_from_json_string (a_json: JSON_STRING)
-- Initialize with `a_json' string value.
do
make_from_escaped_json_string (a_json.item)
end
make_json (s: READABLE_STRING_8)
-- Initialize.
obsolete
"Use `make_from_string' Sept/2014"
require
item_not_void: s /= Void
do
@@ -42,18 +95,12 @@ feature {NONE} -- Initialization
make_json_from_string_32 (s: READABLE_STRING_32)
-- Initialize from STRING_32 `s'.
obsolete
"Use `make_from_string_32' Sept/2014"
require
item_not_void: s /= Void
do
make_with_escaped_json (escaped_json_string_32 (s))
end
make_with_escaped_json (s: READABLE_STRING_8)
-- Initialize with an_item already escaped
require
item_not_void: s /= Void
do
item := s
make_with_escaped_json (escaped_json_string (s))
end
feature -- Access
@@ -61,103 +108,33 @@ feature -- Access
item: STRING
-- Contents with escaped entities if any
feature -- Conversion
unescaped_string_8: STRING_8
-- Unescaped string from `item'
-- Unescaped ascii string from `item'.
--| note: valid only if `item' does not encode any unicode character.
local
s: like item
i, n: INTEGER
c: CHARACTER
do
s := item
n := s.count
create Result.make (n)
from i := 1 until i > n loop
c := s[i]
if c = '\' then
if i < n then
inspect s[i+1]
when '\' then
Result.append_character ('\')
i := i + 2
when '%"' then
Result.append_character ('%"')
i := i + 2
when 'n' then
Result.append_character ('%N')
i := i + 2
when 'r' then
Result.append_character ('%R')
i := i + 2
when 'u' then
--| Leave unicode \uXXXX unescaped
Result.append_character ('\')
i := i + 1
else
Result.append_character ('\')
i := i + 1
end
else
Result.append_character ('\')
i := i + 1
end
else
Result.append_character (c)
i := i + 1
end
end
create Result.make (s.count)
unescape_to_string_8 (Result)
end
unescaped_string_32: STRING_32
-- Unescaped string 32 from `item'
-- Unescaped uncode string from `item'
--| some encoders uses UTF-8 , and not the recommended pure json encoding
--| thus, let's support the UTF-8 encoding during decoding.
local
s: like item
i, n: INTEGER
c: CHARACTER
hex: STRING
s: READABLE_STRING_8
do
s := item
n := s.count
create Result.make (n)
from i := 1 until i > n loop
c := s[i]
if c = '\' then
if i < n then
inspect s[i+1]
when '\' then
Result.append_character ('\')
i := i + 2
when '%"' then
Result.append_character ('%"')
i := i + 2
when 'n' then
Result.append_character ('%N')
i := i + 2
when 'r' then
Result.append_character ('%R')
i := i + 2
when 'u' then
hex := s.substring (i+2, i+2+4 - 1)
if hex.count = 4 then
Result.append_code (hexadecimal_to_natural_32 (hex))
end
i := i + 2 + 4
else
Result.append_character ('\')
i := i + 1
end
else
Result.append_character ('\')
i := i + 1
end
else
Result.append_character (c.to_character_32)
i := i + 1
end
end
create Result.make (s.count)
unescape_to_string_32 (Result)
end
representation: STRING
-- String representation of `item' with escaped entities if any
-- String representation of `item' with escaped entities if any.
do
create Result.make (item.count + 2)
Result.append_character ('%"')
@@ -165,6 +142,160 @@ feature -- Access
Result.append_character ('%"')
end
unescape_to_string_8 (a_output: STRING_8)
-- Unescape string `item' into `a_output'.
--| note: valid only if `item' does not encode any unicode character.
local
s: like item
i, n: INTEGER
c: CHARACTER
do
s := item
n := s.count
from
i := 1
until
i > n
loop
c := s [i]
if c = '\' then
if i < n then
inspect s [i + 1]
when '%"' then
a_output.append_character ('%"')
i := i + 2
when '\' then
a_output.append_character ('\')
i := i + 2
when '/' then
a_output.append_character ('/')
i := i + 2
when 'b' then
a_output.append_character ('%B')
i := i + 2
when 'f' then
a_output.append_character ('%F')
i := i + 2
when 'n' then
a_output.append_character ('%N')
i := i + 2
when 'r' then
a_output.append_character ('%R')
i := i + 2
when 't' then
a_output.append_character ('%T')
i := i + 2
when 'u' then
--| Leave unicode \uXXXX unescaped
a_output.append_character (c) -- '\'
i := i + 1
else
a_output.append_character (c) -- '\'
i := i + 1
end
else
a_output.append_character (c) -- '\'
i := i + 1
end
else
a_output.append_character (c)
i := i + 1
end
end
end
unescape_to_string_32 (a_output: STRING_32)
-- Unescape string `item' into `a_output' string 32.
--| some encoders uses UTF-8 , and not the recommended pure json encoding
--| thus, let's support the UTF-8 encoding during decoding.
local
s: READABLE_STRING_8
i, n: INTEGER
c: NATURAL_32
ch: CHARACTER_8
hex: READABLE_STRING_8
do
s := item
n := s.count
from
i := 1
until
i > n
loop
ch := s.item (i)
if ch = '\' then
if i < n then
inspect s [i + 1]
when '%"' then
a_output.append_character ('%"')
i := i + 2
when '\' then
a_output.append_character ('\')
i := i + 2
when '/' then
a_output.append_character ('/')
i := i + 2
when 'b' then
a_output.append_character ('%B')
i := i + 2
when 'f' then
a_output.append_character ('%F')
i := i + 2
when 'n' then
a_output.append_character ('%N')
i := i + 2
when 'r' then
a_output.append_character ('%R')
i := i + 2
when 't' then
a_output.append_character ('%T')
i := i + 2
when 'u' then
hex := s.substring (i + 2, i + 5) -- i+2 , i+2+4-1
if hex.count = 4 then
a_output.append_code (hexadecimal_to_natural_32 (hex))
end
i := i + 6 -- i+2+4
else
a_output.append_character (ch) -- '\'
i := i + 1
end
else
a_output.append_character (ch) -- '\'
i := i + 1
end
else
c := ch.natural_32_code
if c <= 0x7F then
-- 0xxxxxxx
check
ch = c.to_character_32
end
a_output.append_character (ch)
elseif c <= 0xDF then
-- 110xxxxx 10xxxxxx
i := i + 1
if i <= n then
a_output.append_code (((c & 0x1F) |<< 6) | (s.code (i) & 0x3F))
end
elseif c <= 0xEF then
-- 1110xxxx 10xxxxxx 10xxxxxx
i := i + 2
if i <= n then
a_output.append_code (((c & 0xF) |<< 12) | ((s.code (i - 1) & 0x3F) |<< 6) | (s.code (i) & 0x3F))
end
elseif c <= 0xF7 then
-- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
i := i + 3
if i <= n then
a_output.append_code (((c & 0x7) |<< 18) | ((s.code (i - 2) & 0x3F) |<< 12) | ((s.code (i - 1) & 0x3F) |<< 6) | (s.code (i) & 0x3F))
end
end
i := i + 1
end
end
end
feature -- Visitor pattern
accept (a_visitor: JSON_VISITOR)
@@ -185,12 +316,48 @@ feature -- Comparison
feature -- Change Element
append (a_string: STRING)
-- Add a_string
append (a_escaped_string: READABLE_STRING_8)
-- Add JSON escaped string `a_escaped_string'
require
a_string_not_void: a_string /= Void
a_escaped_string_not_void: a_escaped_string /= Void
do
item.append_string (a_string)
item.append_string (a_escaped_string)
end
append_json_string (a_json_string: JSON_STRING)
-- Add JSON string `a_json_string'
require
a_json_string_not_void: a_json_string /= Void
do
append (a_json_string.item)
end
append_string (s: READABLE_STRING_8)
-- Add ascii string `s'
require
s_not_void: s /= Void
do
append (escaped_json_string (s))
end
append_string_32 (s: READABLE_STRING_32)
-- Add unicode string `s'
require
s_not_void: s /= Void
do
append (escaped_json_string (s))
end
append_string_general (s: READABLE_STRING_GENERAL)
-- Add unicode string `s'
require
s_not_void: s /= Void
do
if attached {READABLE_STRING_8} s as s8 then
append_string (s.as_string_8)
else
append_string_32 (s.as_string_32)
end
end
feature -- Status report
@@ -213,8 +380,18 @@ feature {NONE} -- Implementation
is_hexadecimal (s: READABLE_STRING_8): BOOLEAN
-- Is `s' an hexadecimal value?
local
i: INTEGER
do
Result := across s as scur all scur.item.is_hexa_digit end
from
Result := True
i := 1
until
i > s.count or not Result
loop
Result := s [i].is_hexa_digit
i := i + 1
end
end
hexadecimal_to_natural_32 (s: READABLE_STRING_8): NATURAL_32
@@ -227,13 +404,11 @@ feature {NONE} -- Implementation
char: CHARACTER
do
nb := s.count
if nb >= 2 and then s.item (2) = 'x' then
i := 3
else
i := 1
end
from
until
i > nb
@@ -249,31 +424,7 @@ feature {NONE} -- Implementation
end
end
escaped_json_string (s: READABLE_STRING_8): STRING_8
-- JSON string with '"' and '\' characters escaped
require
s_not_void: s /= Void
local
i, n: INTEGER
c: CHARACTER_8
do
n := s.count
create Result.make (n + n // 10)
from i := 1 until i > n loop
c := s.item (i)
inspect c
when '%"' then Result.append_string ("\%"")
when '\' then Result.append_string ("\\")
when '%R' then Result.append_string ("\r")
when '%N' then Result.append_string ("\n")
else
Result.extend (c)
end
i := i + 1
end
end
escaped_json_string_32 (s: READABLE_STRING_32): STRING_8
escaped_json_string (s: READABLE_STRING_GENERAL): STRING_8
-- JSON string with '"' and '\' characters and unicode escaped
require
s_not_void: s /= Void
@@ -285,15 +436,37 @@ feature {NONE} -- Implementation
do
n := s.count
create Result.make (n + n // 10)
from i := 1 until i > n loop
from
i := 1
until
i > n
loop
uc := s.item (i)
if uc.is_character_8 then
c := uc.to_character_8
inspect c
when '%"' then Result.append_string ("\%"")
when '\' then Result.append_string ("\\")
when '%R' then Result.append_string ("\r")
when '%N' then Result.append_string ("\n")
when '%"' then
Result.append_string ("\%"")
when '\' then
Result.append_string ("\\")
when '/' then
-- To avoid issue with Javascript </script> ...
-- escape only </ to <\/
if s.valid_index (i - 1) and then s.item (i - 1) = '<' then
Result.append_string ("\/")
else
Result.append_string ("/")
end
when '%B' then
Result.append_string ("\b")
when '%F' then
Result.append_string ("\f")
when '%N' then
Result.append_string ("\n")
when '%R' then
Result.append_string ("\r")
when '%T' then
Result.append_string ("\t")
else
Result.extend (c)
end
@@ -309,14 +482,15 @@ feature {NONE} -- Implementation
j := j + 1
end
h := h.substring (j, h.count)
from
until
h.count >= 4
loop
h.prepend_integer (0)
end
check h.count = 4 end
check
hexastring_has_4_chars: h.count = 4
end
Result.append (h)
end
i := i + 1
@@ -326,4 +500,7 @@ feature {NONE} -- Implementation
invariant
item_not_void: item /= Void
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -14,11 +14,11 @@ note
revision: "Revision 0.1"
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
deferred class
JSON_VALUE
inherit
HASHABLE
DEBUG_OUTPUT
@@ -40,4 +40,7 @@ feature -- Visitor pattern
deferred
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -1,513 +0,0 @@
note
description: "Parse serialized JSON data"
author: "jvelilla"
date: "2008/08/24"
revision: "Revision 0.1"
class
JSON_PARSER
inherit
JSON_READER
JSON_TOKENS
create
make_parser
feature {NONE} -- Initialize
make_parser (a_json: STRING)
-- Initialize.
require
json_not_empty: a_json /= Void and then not a_json.is_empty
do
make (a_json)
is_parsed := True
create errors.make
end
feature -- Status report
is_parsed: BOOLEAN
-- Is parsed?
errors: LINKED_LIST [STRING]
-- Current errors
current_errors: STRING
-- Current errors as string
do
create Result.make_empty
from
errors.start
until
errors.after
loop
Result.append_string (errors.item + "%N")
errors.forth
end
end
feature -- Element change
report_error (e: STRING)
-- Report error `e'
require
e_not_void: e /= Void
do
errors.force (e)
end
feature -- Commands
parse_json: detachable JSON_VALUE
-- Parse JSON data `representation'
-- start ::= object | array
do
if is_valid_start_symbol then
Result := parse
if extra_elements then
is_parsed := False
end
else
is_parsed := False
report_error ("Syntax error unexpected token, expecting `{' or `['")
end
end
parse: detachable JSON_VALUE
-- Parse JSON data `representation'
local
c: CHARACTER
do
if is_parsed then
skip_white_spaces
c := actual
inspect c
when j_OBJECT_OPEN then
Result := parse_object
when j_STRING then
Result := parse_string
when j_ARRAY_OPEN then
Result := parse_array
else
if c.is_digit or c = j_MINUS then
Result := parse_number
elseif is_null then
Result := create {JSON_NULL}
next
next
next
elseif is_true then
Result := create {JSON_BOOLEAN}.make_boolean (True)
next
next
next
elseif is_false then
Result := create {JSON_BOOLEAN}.make_boolean (False)
next
next
next
next
else
is_parsed := False
report_error ("JSON is not well formed in parse")
Result := Void
end
end
end
ensure
is_parsed_implies_result_not_void: is_parsed implies Result /= Void
end
parse_object: JSON_OBJECT
-- object
-- {}
-- {"key" : "value" [,]}
local
has_more: BOOLEAN
l_json_string: detachable JSON_STRING
l_value: detachable JSON_VALUE
do
create Result.make
-- check if is an empty object {}
next
skip_white_spaces
if actual = j_OBJECT_CLOSE then
--is an empty object
else
-- a complex object {"key" : "value"}
previous
from has_more := True until not has_more loop
next
skip_white_spaces
l_json_string := parse_string
next
skip_white_spaces
if actual = ':' then
next
skip_white_spaces
else
is_parsed := False
report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out)
has_more := False
end
l_value := parse
if is_parsed and then (l_value /= Void and l_json_string /= Void) then
Result.put (l_value, l_json_string)
next
skip_white_spaces
if actual = j_OBJECT_CLOSE then
has_more := False
elseif actual /= ',' then
has_more := False
is_parsed := False
report_error ("JSON Object syntactically malformed expected , found: [" + actual.out + "]")
end
else
has_more := False
-- explain the error
end
end
end
end
parse_string: detachable JSON_STRING
-- Parsed string
local
has_more: BOOLEAN
l_json_string: STRING
l_unicode: STRING
c: like actual
do
create l_json_string.make_empty
if actual = j_STRING then
from
has_more := True
until
not has_more
loop
next
c := actual
if c = j_STRING then
has_more := False
elseif c = '%H' then
next
c := actual
if c = 'u' then
create l_unicode.make_from_string ("\u")
l_unicode.append (read_unicode)
c := actual
if is_valid_unicode (l_unicode) then
l_json_string.append (l_unicode)
else
has_more := False
is_parsed := False
report_error ("Input String is not well formed JSON, expected a Unicode value, found [" + c.out + " ]")
end
elseif (not is_special_character (c) and not is_special_control (c)) or c = '%N' then
has_more := False
is_parsed := False
report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
else
l_json_string.append_character ('\')
l_json_string.append_character (c)
end
else
if is_special_character (c) and c /= '/' then
has_more := False
is_parsed := False
report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
else
l_json_string.append_character (c)
end
end
end
create Result.make_with_escaped_json (l_json_string)
else
Result := Void
end
end
parse_array: JSON_ARRAY
-- array
-- []
-- [elements [,]]
local
flag: BOOLEAN
l_value: detachable JSON_VALUE
c: like actual
do
create Result.make_array
--check if is an empty array []
next
skip_white_spaces
if actual = j_array_close then
--is an empty array
else
previous
from
flag := True
until
not flag
loop
next
skip_white_spaces
l_value := parse
if is_parsed and then l_value /= Void then
Result.add (l_value)
next
skip_white_spaces
c := actual
if c = j_ARRAY_CLOSE then
flag := False
elseif c /= ',' then
flag := False
is_parsed := False
report_error ("Array is not well formed JSON, found [" + c.out + " ]")
end
else
flag := False
report_error ("Array is not well formed JSON, found [" + actual.out + " ]")
end
end
end
end
parse_number: detachable JSON_NUMBER
-- Parsed number
local
sb: STRING
flag: BOOLEAN
is_integer: BOOLEAN
c: like actual
do
create sb.make_empty
sb.append_character (actual)
from
flag := True
until
not flag
loop
next
c := actual
if not has_next or is_close_token (c)
or c = ',' or c = '%N' or c = '%R'
then
flag := False
previous
else
sb.append_character (c)
end
end
if is_valid_number (sb) then
if sb.is_integer then
create Result.make_integer (sb.to_integer)
is_integer := True
elseif sb.is_double and not is_integer then
create Result.make_real (sb.to_double)
end
else
is_parsed := False
report_error ("Expected a number, found: [ " + sb + " ]")
end
end
is_null: BOOLEAN
-- Word at index represents null?
local
l_null: STRING
l_string: STRING
do
l_null := null_id
l_string := json_substring (index,index + l_null.count - 1)
if l_string.is_equal (l_null) then
Result := True
end
end
is_false: BOOLEAN
-- Word at index represents false?
local
l_false: STRING
l_string: STRING
do
l_false := false_id
l_string := json_substring (index, index + l_false.count - 1)
if l_string.is_equal (l_false) then
Result := True
end
end
is_true: BOOLEAN
-- Word at index represents true?
local
l_true: STRING
l_string: STRING
do
l_true := true_id
l_string := json_substring (index,index + l_true.count - 1)
if l_string.is_equal (l_true) then
Result := True
end
end
read_unicode: STRING
-- Read unicode and return value
local
i: INTEGER
do
create Result.make_empty
from
i := 1
until
i > 4 or not has_next
loop
next
Result.append_character (actual)
i := i + 1
end
end
feature {NONE} -- Implementation
is_valid_number (a_number: STRING): BOOLEAN
-- is 'a_number' a valid number based on this regular expression
-- "-?(?: 0|[1-9]\d+)(?: \.\d+)?(?: [eE][+-]?\d+)?\b"?
local
s: detachable STRING
c: CHARACTER
i,n: INTEGER
do
create s.make_empty
n := a_number.count
if n = 0 then
Result := False
else
Result := True
i := 1
--| "-?"
c := a_number[i]
if c = '-' then
s.extend (c); i := i + 1; c := a_number[i]
end
--| "0|[1-9]\d*
if c.is_digit then
if c = '0' then
--| "0"
s.extend (c); i := i + 1; c := a_number[i]
else
--| "[1-9]"
s.extend (c); i := i + 1; c := a_number[i]
--| "\d*"
from until i > n or not c.is_digit loop
s.extend (c); i := i + 1; c := a_number[i]
end
end
end
end
if Result then
--| "(\.\d+)?"
if c = '.' then
--| "\.\d+" = "\.\d\d*"
s.extend (c); i := i + 1; c := a_number[i]
if c.is_digit then
from until i > n or not c.is_digit loop
s.extend (c); i := i + 1; c := a_number[i]
end
else
Result := False --| expecting digit
end
end
end
if Result then --| "(?:[eE][+-]?\d+)?\b"
if c = 'e' or c = 'E' then
--| "[eE][+-]?\d+"
s.extend (c); i := i + 1; c := a_number[i]
if c = '+' or c = '-' then
s.extend (c); i := i + 1; c := a_number[i]
end
if c.is_digit then
from until i > n or not c.is_digit loop
s.extend (c); i := i + 1; c := a_number[i]
end
else
Result := False --| expecting digit
end
end
end
if Result then --| "\b"
from until i > n or not c.is_space loop
s.extend (c); i := i + 1; c := a_number[i]
end
Result := i > n and then s.same_string (a_number)
end
end
is_valid_unicode (a_unicode: STRING): BOOLEAN
-- is 'a_unicode' a valid unicode based on this regular expression
-- "\\u[0-9a-fA-F]{4}"
local
i: INTEGER
do
if
a_unicode.count = 6 and then
a_unicode[1] = '\' and then
a_unicode[2] = 'u'
then
from
Result := True
i := 3
until
i > 6 or Result = False
loop
inspect a_unicode[i]
when '0'..'9', 'a'..'f', 'A'..'F' then
else
Result := False
end
i := i + 1
end
end
end
extra_elements: BOOLEAN
-- has more elements?
local
c: like actual
do
if has_next then
next
end
from
c := actual
until
c /= ' ' or c /= '%R' or c /= '%U' or c /= '%T' or c /= '%N' or not has_next
loop
next
end
Result := has_next
end
is_valid_start_symbol : BOOLEAN
-- expecting `{' or `[' as start symbol
do
if attached representation as s and then s.count > 0 then
Result := s[1] = '{' or s[1] = '['
end
end
feature {NONE} -- Constants
false_id: STRING = "false"
true_id: STRING = "true"
null_id: STRING = "null"
end

View File

@@ -1,77 +0,0 @@
note
description: ""
author: "jvelilla"
date: "2008/08/24"
revision: "0.1"
class
JSON_TOKENS
feature -- Access
j_OBJECT_OPEN: CHARACTER = '{'
j_ARRAY_OPEN: CHARACTER = '['
j_OBJECT_CLOSE: CHARACTER = '}'
j_ARRAY_CLOSE: CHARACTER = ']'
j_STRING: CHARACTER = '"'
j_PLUS: CHARACTER = '+'
j_MINUS: CHARACTER = '-'
j_DOT: CHARACTER = '.'
feature -- Status report
is_open_token (c: CHARACTER): BOOLEAN
-- Characters which open a type
do
inspect c
when j_OBJECT_OPEN, j_ARRAY_OPEN, j_STRING, j_PLUS, j_MINUS, j_DOT then
Result := True
else
end
end
is_close_token (c: CHARACTER): BOOLEAN
-- Characters which close a type
do
inspect c
when j_OBJECT_CLOSE, j_ARRAY_CLOSE, j_STRING then
Result := True
else
end
end
is_special_character (c: CHARACTER): BOOLEAN
-- Control Characters
-- %F Form feed
-- %H backslasH
-- %N Newline
-- %R carriage Return
-- %T horizontal Tab
-- %B Backspace
-- / Solidus
-- " Quotation
do
inspect c
when '%F', '%H', '%N', '%R', '%T', '%B', '/', '"' then
Result := True
else
end
end
is_special_control (c: CHARACTER): BOOLEAN
--Control Characters
-- \b\f\n\r\t
do
inspect c
when 'b', 'f', 'n', 'r', 't' then
Result := True
else
end
end
end

View File

@@ -1,38 +0,0 @@
note
description: "[
Shared factory class for creating JSON objects. Maps JSON
objects to ELKS HASH_TABLEs and JSON arrays to ELKS
LINKED_LISTs. Use non-conforming inheritance from this
class to ensure that your classes share the same
JSON_FACTORY instance.
]"
author: "Paul Cohen"
date: "$Date$"
revision: "$Revision: 89185 $"
file: "$HeadURL: $"
class SHARED_EJSON
feature
json: EJSON
-- A shared EJSON instance with default converters for
--LINKED_LIST [ANY] and HASH_TABLE [ANY, HASHABLE]
local
jalc: JSON_ARRAYED_LIST_CONVERTER
jllc: JSON_LINKED_LIST_CONVERTER
jhtc: JSON_HASH_TABLE_CONVERTER
once
create Result
create jalc.make
Result.add_converter (jalc)
create jllc.make
Result.add_converter (jllc)
create jhtc.make
Result.add_converter (jhtc)
end
end -- class SHARED_EJSON

View File

@@ -0,0 +1,4 @@
${NOTE_KEYWORD}
copyright: "2010-${YEAR}, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"

View File

@@ -0,0 +1,679 @@
note
description: "Parse serialized JSON data"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
class
JSON_PARSER
inherit
JSON_READER
rename
make as make_reader,
reset as reset_reader
end
JSON_TOKENS
create
make_with_string,
make_parser
feature {NONE} -- Initialize
make_with_string (a_content: STRING)
-- Initialize parser with JSON content `a_content'.
require
a_content_not_empty: a_content /= Void and then not a_content.is_empty
do
create errors.make
make_reader (a_content)
reset
end
make_parser (a_json: STRING)
-- Initialize.
obsolete
"Use `make_with_string' [sept/2014]."
do
make_with_string (a_json)
end
feature -- Status report
is_parsed: BOOLEAN
-- Is parsed ?
is_valid: BOOLEAN
-- Is valid?
do
Result := not has_error
end
has_error: BOOLEAN
-- Has error?
errors: LINKED_LIST [STRING]
-- Current errors
errors_as_string: STRING
-- String representation of `errors'.
do
create Result.make_empty
across
errors as ic
loop
Result.append_string (ic.item)
Result.append_character ('%N')
end
end
current_errors: STRING
-- Current errors as string
obsolete
"USe errors_as_string [sept/2014]"
do
Result := errors_as_string
end
feature -- Access
parsed_json_value: detachable JSON_VALUE
-- Parsed json value if any.
require
is_parsed: is_parsed
attribute
ensure
attached_result_if_valid: is_valid implies Result /= Void
end
parsed_json_object: detachable JSON_OBJECT
-- parsed json value as a JSON_OBJECT if it is an object.
require
is_parsed: is_parsed
do
if attached {JSON_OBJECT} parsed_json_value as j_object then
Result := j_object
end
end
parsed_json_array: detachable JSON_ARRAY
-- parsed json value as a JSON_OBJECT if it is an array.
require
is_parsed: is_parsed
do
if attached {JSON_ARRAY} parsed_json_value as j_array then
Result := j_array
end
end
feature -- Commands
reset
-- Reset parsing values.
do
parsed_json_value := Void
errors.wipe_out
has_error := False
is_parsed := False
end
parse_content
-- Parse JSON content `representation'.
-- start ::= object | array
do
reset
reset_reader
if is_valid_start_symbol then
parsed_json_value := next_json_value
if extra_elements then
report_error ("Remaining element outside the main json value!")
end
else
report_error ("Syntax error unexpected token, expecting `{' or `['")
end
is_parsed := is_valid
end
feature -- Element change
report_error (e: STRING)
-- Report error `e'
require
e_not_void: e /= Void
do
has_error := True
errors.force (e)
ensure
has_error: has_error
is_not_valid: not is_valid
end
feature -- Obsolete commands
parse_json: detachable JSON_VALUE
-- Parse JSON data `representation'
-- start ::= object | array
obsolete
"Use `parse_content' and `parsed_json_value' [sept/2014]."
do
parse_content
if is_parsed then
Result := parsed_json_value
end
end
parse_object: detachable JSON_OBJECT
-- Parse JSON data `representation'
-- start ::= object | array
obsolete
"Use `parse_content' and `parsed_json_value' [nov/2014]."
do
parse_content
if is_parsed and then attached {JSON_OBJECT} parsed_json_value as jo then
Result := jo
end
end
parse: detachable JSON_VALUE
-- Next JSON value from current position on `representation'.
obsolete
"Use restricted `next_parsed_json_value' [sept/2014]."
do
Result := next_parsed_json_value
is_parsed := is_valid
end
feature {JSON_PARSER_ACCESS} -- Obsolete commands: restricted area
next_parsed_json_value: detachable JSON_VALUE
-- Return next json value from current position.
--| this does not call `reset_reader'.
do
reset
Result := next_json_value
end
feature {NONE} -- Implementation: parsing
next_json_value: detachable JSON_VALUE
-- Next JSON value from current position on `representation'.
local
c: CHARACTER
do
if not has_error then
skip_white_spaces
c := actual
inspect c
when token_object_open then
Result := next_json_object
when token_double_quote then
Result := parse_string
when token_array_open then
Result := parse_array
else
if c.is_digit or c = token_minus then
Result := parse_number
elseif is_null then
Result := create {JSON_NULL}
next
next
next
elseif is_true then
Result := create {JSON_BOOLEAN}.make_true
next
next
next
elseif is_false then
Result := create {JSON_BOOLEAN}.make_false
next
next
next
next
else
report_error ("JSON is not well formed in parse")
Result := Void
end
end
end
ensure
is_parsed_implies_result_not_void: not has_error implies Result /= Void
end
next_json_object: JSON_OBJECT
-- object
-- {}
-- {"key" : "value" [,]}
local
has_more: BOOLEAN
l_json_string: detachable JSON_STRING
l_value: detachable JSON_VALUE
do
create Result.make
--| check if is an empty object {}
next
skip_white_spaces
if actual = token_object_close then
--| is an empty object
else
--| a complex object {"key" : "value"}
previous
from
has_more := True
until
not has_more
loop
next
skip_white_spaces
l_json_string := parse_string
next
skip_white_spaces
if actual = token_colon then --| token_colon = ':'
next
skip_white_spaces
else
report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out)
has_more := False
end
l_value := next_json_value
if not has_error and then (l_value /= Void and l_json_string /= Void) then
Result.put (l_value, l_json_string)
next
skip_white_spaces
if actual = token_object_close then
has_more := False
elseif actual /= token_comma then
has_more := False
report_error ("JSON Object syntactically malformed expected , found: [" + actual.out + "]")
end
else
has_more := False
-- explain the error
end
end
end
end
parse_string: detachable JSON_STRING
-- Parsed string
local
has_more: BOOLEAN
l_json_string: STRING
l_unicode: STRING
c: like actual
do
create l_json_string.make_empty
if actual = token_double_quote then
from
has_more := True
until
not has_more
loop
next
c := actual
if c = token_double_quote then
has_more := False
elseif c = '%H' then -- '%H' = '\' = reverse solidus
next
c := actual
if c = 'u' then
create l_unicode.make_from_string ("\u")
l_unicode.append (read_unicode)
c := actual
if is_valid_unicode (l_unicode) then
l_json_string.append (l_unicode)
else
has_more := False
report_error ("Input String is not well formed JSON, expected a Unicode value, found [" + c.out + " ]")
end
elseif (not is_special_character (c) and not is_special_control (c)) or c = '%N' then
has_more := False
report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
else
l_json_string.append_character ('\')
l_json_string.append_character (c)
end
else
if is_special_character (c) and c /= '/' then
has_more := False
report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
else
l_json_string.append_character (c)
end
end
end
create Result.make_from_escaped_json_string (l_json_string)
else
Result := Void
end
end
parse_array: JSON_ARRAY
-- array
-- []
-- [elements [,]]
local
flag: BOOLEAN
l_value: detachable JSON_VALUE
c: like actual
do
create Result.make_empty
-- check if is an empty array []
next
skip_white_spaces
if actual = token_array_close then
-- is an empty array
else
previous
from
flag := True
until
not flag
loop
next
skip_white_spaces
l_value := next_json_value
if not has_error and then l_value /= Void then
Result.add (l_value)
next
skip_white_spaces
c := actual
if c = token_array_close then
flag := False
elseif c /= token_comma then
flag := False
report_error ("Array is not well formed JSON, found [" + c.out + " ]")
end
else
flag := False
report_error ("Array is not well formed JSON, found [" + actual.out + " ]")
end
end
end
end
parse_number: detachable JSON_NUMBER
-- Parsed number
local
sb: STRING
flag: BOOLEAN
is_integer: BOOLEAN
c: like actual
do
create sb.make_empty
sb.append_character (actual)
from
flag := True
until
not flag
loop
next
c := actual
if not has_next or is_close_token (c) or c = token_comma or c = '%N' or c = '%R' then
flag := False
previous
else
sb.append_character (c)
end
end
if is_valid_number (sb) then
if sb.is_integer then
create Result.make_integer (sb.to_integer)
is_integer := True
elseif sb.is_double and not is_integer then
create Result.make_real (sb.to_double)
end
else
report_error ("Expected a number, found: [ " + sb + " ]")
end
end
is_null: BOOLEAN
-- Word at index represents null?
local
l_null: STRING
l_string: STRING
do
l_null := null_id
l_string := json_substring (index, index + l_null.count - 1)
if l_string.is_equal (l_null) then
Result := True
end
end
is_false: BOOLEAN
-- Word at index represents false?
local
l_false: STRING
l_string: STRING
do
l_false := false_id
l_string := json_substring (index, index + l_false.count - 1)
if l_string.is_equal (l_false) then
Result := True
end
end
is_true: BOOLEAN
-- Word at index represents true?
local
l_true: STRING
l_string: STRING
do
l_true := true_id
l_string := json_substring (index, index + l_true.count - 1)
if l_string.is_equal (l_true) then
Result := True
end
end
read_unicode: STRING
-- Read unicode and return value.
local
i: INTEGER
do
create Result.make_empty
from
i := 1
until
i > 4 or not has_next
loop
next
Result.append_character (actual)
i := i + 1
end
end
feature {NONE} -- Implementation
is_valid_number (a_number: STRING): BOOLEAN
-- is 'a_number' a valid number based on this regular expression
-- "-?(?: 0|[1-9]\d+)(?: \.\d+)?(?: [eE][+-]?\d+)?\b"?
local
s: detachable STRING
c: CHARACTER
i, n: INTEGER
do
create s.make_empty
n := a_number.count
if n = 0 then
Result := False
else
Result := True
i := 1
--| "-?"
c := a_number [i]
if c = token_minus then
s.extend (c)
i := i + 1
if i > n then
Result := False
else
c := a_number [i]
end
end
--| "0|[1-9]\d*
if Result and c.is_digit then
if c = '0' then
--| "0"
s.extend (c)
i := i + 1
if i <= n then
c := a_number [i]
end
else
--| "[1-9]"
s.extend (c)
--| "\d*"
i := i + 1
if i <= n then
c := a_number [i]
from
until
i > n or not c.is_digit
loop
s.extend (c)
i := i + 1
if i <= n then
c := a_number [i]
end
end
end
end
end
end
if i > n then
-- Exit
else
if Result then
--| "(\.\d+)?"
if c = token_dot then
--| "\.\d+" = "\.\d\d*"
s.extend (c)
i := i + 1
c := a_number [i]
if c.is_digit then
from
until
i > n or not c.is_digit
loop
s.extend (c)
i := i + 1
if i <= n then
c := a_number [i]
end
end
else
Result := False --| expecting digit
end
end
end
if Result then --| "(?:[eE][+-]?\d+)?\b"
if is_exp_token (c) then
--| "[eE][+-]?\d+"
s.extend (c)
i := i + 1
c := a_number [i]
if c = token_plus or c = token_minus then
s.extend (c)
i := i + 1
if i <= n then
c := a_number [i]
end
end
if c.is_digit then
from
until
i > n or not c.is_digit
loop
s.extend (c)
i := i + 1
if i <= n then
c := a_number [i]
end
end
else
Result := False --| expecting digit
end
end
end
if Result then --| "\b"
from
until
i > n or not c.is_space
loop
s.extend (c)
i := i + 1
if i <= n then
c := a_number [i]
end
end
Result := i > n and then s.same_string (a_number)
end
end
end
is_valid_unicode (a_unicode: STRING): BOOLEAN
-- is 'a_unicode' a valid unicode based on the regular expression "\\u[0-9a-fA-F]{4}" .
local
i: INTEGER
do
if a_unicode.count = 6 and then a_unicode [1] = '\' and then a_unicode [2] = 'u' then
from
Result := True
i := 3
until
i > 6 or Result = False
loop
inspect a_unicode [i]
when '0'..'9', 'a'..'f', 'A'..'F' then
else
Result := False
end
i := i + 1
end
end
end
extra_elements: BOOLEAN
-- has more elements?
local
c: like actual
do
if has_next then
next
end
from
c := actual
until
c /= ' ' or c /= '%R' or c /= '%U' or c /= '%T' or c /= '%N' or not has_next
loop
next
end
Result := has_next
end
is_valid_start_symbol: BOOLEAN
-- expecting `{' or `[' as start symbol
do
if attached representation as s and then s.count > 0 then
Result := s [1] = token_object_open or s [1] = token_array_open
end
end
feature {NONE} -- Constants
false_id: STRING = "false"
true_id: STRING = "true"
null_id: STRING = "null"
note
copyright: "2010-2015, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -0,0 +1,12 @@
note
description: "Inherit to access restricted feature from {JSON_PARSER}."
date: "$Date$"
revision: "$Revision$"
deferred class
JSON_PARSER_ACCESS
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -20,13 +20,19 @@ feature {NONE} -- Initialization
feature -- Commands
reset
-- Reset reader
do
index := 1
end
set_representation (a_json: STRING)
-- Set `representation'.
do
a_json.left_adjust
a_json.right_adjust
representation := a_json
index := 1
reset
end
read: CHARACTER
@@ -115,4 +121,7 @@ feature {NONE} -- Implementation
invariant
representation_not_void: representation /= Void
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -0,0 +1,90 @@
note
description: "Token used by the JSON_PARSER"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
class
JSON_TOKENS
feature -- Access
token_object_open: CHARACTER = '{'
token_object_close: CHARACTER = '}'
token_array_open: CHARACTER = '['
token_array_close: CHARACTER = ']'
token_double_quote: CHARACTER = '"'
token_plus: CHARACTER = '+'
token_minus: CHARACTER = '-'
token_dot: CHARACTER = '.'
token_exp: CHARACTER = 'e'
token_comma: CHARACTER = ','
token_colon: CHARACTER = ':'
feature -- Status report
is_open_token (c: CHARACTER): BOOLEAN
-- Characters which open a type
do
inspect c
when token_object_open, token_array_open, token_double_quote, token_plus, token_minus, token_dot then
Result := True
else
end
end
is_close_token (c: CHARACTER): BOOLEAN
-- Characters which close a type
do
inspect c
when token_object_close, token_array_close, token_double_quote then
Result := True
else
end
end
is_special_character (c: CHARACTER): BOOLEAN
-- Control Characters
-- %F Form feed
-- %H backslasH
-- %N Newline
-- %R carriage Return
-- %T horizontal Tab
-- %B Backspace
-- / Solidus
-- " Quotation
do
inspect c
when '"', '%H' , '/', '%B', '%F', '%N', '%R', '%T' then -- '%H' = '\' = reverse solidus
Result := True
else
end
end
is_special_control (c: CHARACTER): BOOLEAN
-- Control Characters
-- \b\f\n\r\t
do
inspect c
when 'b', 'f', 'n', 'r', 't' then
Result := True
else
end
end
is_exp_token (c: CHARACTER): BOOLEAN
-- Is number exposant token?
do
Result := c = token_exp or else c.as_lower = token_exp
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -0,0 +1,49 @@
note
description: "Objects that ..."
author: ""
date: "$Date$"
revision: "$Revision$"
class
JSON_FILE_READER
feature -- Access
read_json_from (a_path: READABLE_STRING_GENERAL): detachable STRING
local
l_file: PLAIN_TEXT_FILE
l_last_string: detachable STRING
l_file_count: INTEGER
l_fetch_done: BOOLEAN
do
create l_file.make_with_name (a_path)
-- We perform several checks until we make a real attempt to open the file.
if not l_file.exists then
print ("error: '" + a_path.out + "' does not exist%N") -- FIXME: unicode may be truncated
else
if not l_file.is_readable then
print ("error: '" + a_path.out + "' is not readable.%N") -- FIXME: unicode may be truncated
else
l_file_count := l_file.count
l_file.open_read
from
create Result.make (l_file_count)
until
l_fetch_done
loop
l_file.read_stream (1_024)
l_last_string := l_file.last_string
l_fetch_done := l_file.exhausted or l_file.end_of_file or l_last_string.count < 1_024
if not l_last_string.is_empty then
Result.append (l_last_string)
end
end
l_file.close
end
end
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -0,0 +1,61 @@
note
description: "JSON Iterator"
pattern: "Iterator visitor"
author: "Jocelyn Fiat"
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
date: "2013/08/01"
revision: "Revision 0.1"
deferred class
JSON_ITERATOR
inherit
JSON_VISITOR
feature -- Visitor Pattern
visit_json_array (a_json_array: JSON_ARRAY)
-- Visit `a_json_array'.
do
across
a_json_array as c
loop
c.item.accept (Current)
end
end
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
-- Visit `a_json_boolean'.
do
end
visit_json_null (a_json_null: JSON_NULL)
-- Visit `a_json_null'.
do
end
visit_json_number (a_json_number: JSON_NUMBER)
-- Visit `a_json_number'.
do
end
visit_json_object (a_json_object: JSON_OBJECT)
-- Visit `a_json_object'.
do
across
a_json_object as c
loop
c.item.accept (Current)
end
end
visit_json_string (a_json_string: JSON_STRING)
-- Visit `a_json_string'.
do
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -6,6 +6,7 @@ class
JSON_PRETTY_STRING_VISITOR
inherit
JSON_VISITOR
create
@@ -26,21 +27,58 @@ feature -- Initialization
output := a_output
create indentation.make_empty
indentation_step := "%T"
object_count_inlining := a_object_count_inlining
array_count_inlining := a_array_count_inlining
end
feature -- Access
output: STRING_32
output: STRING_GENERAL
-- JSON representation
indentation: like output
feature -- Settings
indentation_step: like indentation
indentation_step: STRING
-- Text used for indentation.
--| by default a tabulation "%T"
line_number: INTEGER
object_count_inlining: INTEGER
-- Inline where object item count is under `object_count_inlining'.
--| ex 3:
--| { "a", "b", "c" }
--| ex 2:
--| {
--| "a",
--| "b",
--| "c"
--| }
array_count_inlining: INTEGER
-- Inline where array item count is under `object_count_inlining'.
feature -- Element change
set_indentation_step (a_step: STRING)
-- Set `indentation_step' to `a_step'.
do
indentation_step := a_step
end
set_object_count_inlining (a_nb: INTEGER)
-- Set `object_count_inlining' to `a_nb'.
do
object_count_inlining := a_nb
end
set_array_count_inlining (a_nb: INTEGER)
-- Set `array_count_inlining' to `a_nb'.
do
array_count_inlining := a_nb
end
feature {NONE} -- Implementation
indentation: STRING
indent
do
@@ -59,8 +97,7 @@ feature -- Access
line_number := line_number + 1
end
object_count_inlining: INTEGER
array_count_inlining: INTEGER
line_number: INTEGER
feature -- Visitor Pattern
@@ -71,10 +108,14 @@ feature -- Visitor Pattern
l_json_array: ARRAYED_LIST [JSON_VALUE]
l_line: like line_number
l_multiple_lines: BOOLEAN
l_output: like output
do
l_output := output
l_json_array := a_json_array.array_representation
l_multiple_lines := l_json_array.count >= array_count_inlining or across l_json_array as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
output.append ("[")
l_multiple_lines := l_json_array.count >= array_count_inlining
or across l_json_array as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
l_output.append_code (91) -- '[' : 91
l_line := line_number
indent
from
@@ -82,27 +123,21 @@ feature -- Visitor Pattern
until
l_json_array.off
loop
if
line_number > l_line or
l_multiple_lines
then
if line_number > l_line or l_multiple_lines then
new_line
end
value := l_json_array.item
value.accept (Current)
l_json_array.forth
if not l_json_array.after then
output.append (", ")
l_output.append (", ")
end
end
exdent
if
line_number > l_line or
l_json_array.count >= array_count_inlining
then
if line_number > l_line or l_json_array.count >= array_count_inlining then
new_line
end
output.append ("]")
l_output.append_code (93) -- ']' : 93
end
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
@@ -129,10 +164,12 @@ feature -- Visitor Pattern
l_pairs: HASH_TABLE [JSON_VALUE, JSON_STRING]
l_line: like line_number
l_multiple_lines: BOOLEAN
l_output: like output
do
l_output := output
l_pairs := a_json_object.map_representation
l_multiple_lines := l_pairs.count >= object_count_inlining or across l_pairs as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
output.append ("{")
l_output.append_code (123) -- '{' : 123
l_line := line_number
indent
from
@@ -140,36 +177,36 @@ feature -- Visitor Pattern
until
l_pairs.off
loop
if
line_number > l_line or
l_multiple_lines
then
if line_number > l_line or l_multiple_lines then
new_line
end
l_pairs.key_for_iteration.accept (Current)
output.append (": ")
l_output.append (": ")
l_pairs.item_for_iteration.accept (Current)
l_pairs.forth
if not l_pairs.after then
output.append (", ")
l_output.append (", ")
end
end
exdent
if
line_number > l_line or
l_pairs.count >= object_count_inlining
then
if line_number > l_line or l_pairs.count >= object_count_inlining then
new_line
end
output.append ("}")
l_output.append_code (125) -- '}' : 125
end
visit_json_string (a_json_string: JSON_STRING)
-- Visit `a_json_string'.
local
l_output: like output
do
output.append ("%"")
output.append (a_json_string.item)
output.append ("%"")
l_output := output
l_output.append_code (34) -- '%"' : 34
l_output.append (a_json_string.item)
l_output.append_code (34) -- '%"' : 34
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -1,8 +1,5 @@
note
description:
"JSON Visitor"
description: "JSON Visitor"
pattern: "Visitor"
author: "Javier Velilla"
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
@@ -56,4 +53,7 @@ feature -- Visitor Pattern
deferred
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -8,9 +8,11 @@ class
PRINT_JSON_VISITOR
inherit
JSON_VISITOR
create make
create
make
feature -- Initialization
@@ -99,4 +101,7 @@ feature -- Visitor Pattern
to_json.append ("%"")
end
note
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
end

View File

@@ -0,0 +1,16 @@
package json
project
json_safe = "library/json-safe.ecf"
json = "library/json.ecf"
json_gobo_extension = "library/json_gobo_extension.ecf"
note
title: Eiffel JSON
description: Eiffel JSON parser and visitors
tags: json,parser,text
license: MIT
copyright: Copyright (c) 2010-2014 Javier Velilla, Jocelyn Fiat and others,
link[github]: "project" https://github.com/eiffelhub/json
end

View File

@@ -7,6 +7,7 @@ class
APPLICATION
inherit
ARGUMENTS
create

View File

@@ -1,4 +1,5 @@
class AUTHOR
class
AUTHOR
create
make
@@ -6,19 +7,26 @@ create
feature {NONE} -- Initialization
make (a_name: STRING_32)
-- Create an author with `a_name' as `name'.
do
set_name (a_name)
ensure
name_set: name = a_name
end
feature -- Access
name: STRING_32
-- Author name
feature -- Status setting
feature -- Change
set_name (a_name: STRING_32)
-- Set `name' with `a_name'.
do
name := a_name
ensure
name_set: name = a_name
end
end -- class AUTHOR

View File

@@ -1,40 +1,59 @@
class BOOK
class
BOOK
create
make
feature {NONE} -- Initialization
make (a_title: STRING_32; an_author: AUTHOR; an_isbn: STRING_32)
make (a_title: STRING_32; a_author: AUTHOR; a_isbn: STRING_32)
-- Create a book with `a_title' as `title',
-- `a_author' as `author', and `a_isbn' as `isbn'.
do
set_title (a_title)
set_author (an_author)
set_isbn (an_isbn)
set_author (a_author)
set_isbn (a_isbn)
ensure
title_set: title = a_title
author_set: author = a_author
isbn_set: isbn = a_isbn
end
feature -- Access
title: STRING_32
-- Main title.
isbn: STRING_32
-- ISBN.
author: AUTHOR
-- Author.
feature -- Status setting
feature -- Change
set_title (a_title: STRING_32)
-- Set `title' with `a_title'.
do
title := a_title
ensure
title_set: title = a_title
end
set_author (an_author: AUTHOR)
set_author (a_author: AUTHOR)
-- Set `author' with `a_author'.
do
author := an_author
author := a_author
ensure
author_set: author = a_author
end
set_isbn (an_isbn: STRING_32)
set_isbn (a_isbn: STRING_32)
-- Set `isbn' with `a_isbn'.
do
isbn := an_isbn
isbn := a_isbn
ensure
isbn_set: isbn = a_isbn
end
end -- class BOOK

View File

@@ -1,4 +1,5 @@
class BOOK_COLLECTION
class
BOOK_COLLECTION
create
make
@@ -6,75 +7,76 @@ create
feature {NONE} -- Initialization
make (a_name: STRING_32)
-- Create a book collection with `a_name' as `name'.
do
set_name (a_name)
create book_index.make (10)
ensure
name_set: name = a_name
end
feature -- Access
name: STRING_32
-- Name.
books: LIST [BOOK]
-- collection of book.
do
from
create {LINKED_LIST [BOOK]} Result.make
book_index.start
until
book_index.after
across
book_index as it
loop
Result.append (book_index.item_for_iteration)
book_index.forth
Result.append (it.item)
end
end
books_by_author (an_author: STRING_32): detachable LIST [BOOK]
books_by_author (a_author: STRING_32): LIST [BOOK]
-- Books wrote by `a_author' in this collection.
do
if book_index.has (an_author) then
Result := book_index @ an_author
if attached book_index [a_author] as l_result then
Result := l_result
else
create {LINKED_LIST [BOOK]} Result.make
end
end
feature -- Status setting
feature -- Change
set_name (a_name: STRING_32)
-- Set `name' with `a_name'.
do
name := a_name
ensure
name_set: name = a_name
end
add_book (a_book: BOOK)
-- Extend collection with `a_book'.
local
l: detachable LIST [BOOK]
do
if book_index.has (a_book.author.name) then
l := book_index.at (a_book.author.name)
else
if l = Void then
create {LINKED_LIST [BOOK]} l.make
book_index.put (l, a_book.author.name)
end
if attached l as la then
la.force (a_book)
end
l.force (a_book)
end
add_books (book_list: like books)
-- Append collection with `book_list'.
do
from
book_list.start
until
book_list.after
across
book_list as it
loop
add_book (book_list.item)
book_list.forth
add_book (it.item)
end
end
feature {NONE} -- Implementation
book_index: HASH_TABLE [LIST [BOOK], STRING_32]
-- Association of author name and its books.
end -- class BOOK_COLLECTION

View File

@@ -4,9 +4,11 @@ note
date: "$Date$"
revision: "$Revision$"
class JSON_AUTHOR_CONVERTER
class
JSON_AUTHOR_CONVERTER
inherit
JSON_CONVERTER
create
@@ -29,12 +31,10 @@ feature -- Access
feature -- Conversion
from_json (j: like to_json): detachable like object
local
ucs: detachable STRING_32
do
ucs ?= json.object (j.item (name_key), Void)
check ucs /= Void end
create Result.make (ucs)
if attached {STRING_32} json.object (j.item (name_key), Void) as l_name then
create Result.make (l_name)
end
end
to_json (o: like object): JSON_OBJECT
@@ -46,8 +46,9 @@ feature -- Conversion
feature {NONE} -- Implementation
name_key: JSON_STRING
-- Author's name label.
once
create Result.make_json ("name")
create Result.make_from_string ("name")
end
end -- class JSON_AUTHOR_CONVERTER

View File

@@ -4,9 +4,11 @@ note
date: "$Date$"
revision: "$Revision$"
class JSON_BOOK_COLLECTION_CONVERTER
class
JSON_BOOK_COLLECTION_CONVERTER
inherit
JSON_CONVERTER
create
@@ -30,35 +32,35 @@ feature -- Conversion
from_json (j: like to_json): detachable like object
local
ucs: detachable STRING_32
ll: LINKED_LIST [BOOK]
b: detachable BOOK
ja: detachable JSON_ARRAY
i: INTEGER
l_books: LINKED_LIST [BOOK]
do
ucs ?= json.object (j.item (name_key), Void)
check ucs /= Void end
create Result.make (ucs)
ja ?= j.item (books_key)
check ja /= Void end
from
i := 1
create ll.make
if
attached {STRING_32} json.object (j.item (name_key), Void) as l_name and
attached {JSON_ARRAY} j.item (books_key) as l_json_array
then
create Result.make (l_name)
create l_books.make
across
l_json_array as it
until
i > ja.count
Result = Void
loop
b ?= json.object (ja [i], "BOOK")
check b /= Void end
ll.force (b)
i := i + 1
if attached {BOOK} json.object (it.item, "BOOK") as l_book then
l_books.extend (l_book)
else
Result := Void
-- Failed
end
end
if Result /= Void then
Result.add_books (l_books)
end
end
check ll /= Void end
Result.add_books (ll)
end
to_json (o: like object): JSON_OBJECT
do
create Result.make
create Result.make_with_capacity (2)
Result.put (json.value (o.name), name_key)
Result.put (json.value (o.books), books_key)
end
@@ -66,13 +68,15 @@ feature -- Conversion
feature {NONE} -- Implementation
name_key: JSON_STRING
-- Collection's name label.
once
create Result.make_json ("name")
create Result.make_from_string ("name")
end
books_key: JSON_STRING
-- Book list label.
once
create Result.make_json ("books")
create Result.make_from_string ("books")
end
end -- class JSON_BOOK_COLLECTION_CONVERTER

View File

@@ -4,9 +4,11 @@ note
date: "$Date$"
revision: "$Revision$"
class JSON_BOOK_CONVERTER
class
JSON_BOOK_CONVERTER
inherit
JSON_CONVERTER
create
@@ -31,22 +33,19 @@ feature -- Access
feature -- Conversion
from_json (j: like to_json): detachable like object
local
ucs1, ucs2: detachable STRING_32
a: detachable AUTHOR
do
ucs1 ?= json.object (j.item (title_key), Void)
check ucs1 /= Void end
ucs2 ?= json.object (j.item (isbn_key), Void)
check ucs2 /= Void end
a ?= json.object (j.item (author_key), "AUTHOR")
check a /= Void end
create Result.make (ucs1, a, ucs2)
if
attached {STRING_32} json.object (j.item (title_key), Void) as l_title and
attached {STRING_32} json.object (j.item (isbn_key), Void) as l_isbn and
attached {AUTHOR} json.object (j.item (author_key), "AUTHOR") as l_author
then
create Result.make (l_title, l_author, l_isbn)
end
end
to_json (o: like object): JSON_OBJECT
do
create Result.make
create Result.make_with_capacity (3)
Result.put (json.value (o.title), title_key)
Result.put (json.value (o.isbn), isbn_key)
Result.put (json.value (o.author), author_key)
@@ -55,18 +54,21 @@ feature -- Conversion
feature {NONE} -- Implementation
title_key: JSON_STRING
-- Book's title label.
once
create Result.make_json ("title")
create Result.make_from_string ("title")
end
isbn_key: JSON_STRING
-- Book ISBN label.
once
create Result.make_json ("isbn")
create Result.make_from_string ("isbn")
end
author_key: JSON_STRING
-- Author label.
once
create Result.make_json ("author")
create Result.make_from_string ("author")
end
end -- class JSON_BOOK_CONVERTER

View File

@@ -1,73 +1,71 @@
class TEST_DS
note
description: "Linked list and hash table converters test."
date: "$Date$"
revision: "$Revision$"
class
TEST_DS
inherit
SHARED_EJSON
rename default_create as shared_default_create end
EQA_TEST_SET
select default_create end
SHARED_EJSON
undefine
default_create
end
EQA_TEST_SET
feature -- Test
test_linked_list_converter
-- Convert a linked list to a json value and
-- convert this one to a linked list.
local
jc: JSON_LINKED_LIST_CONVERTER
l: LINKED_LIST [STRING]
l2: detachable LINKED_LIST [detachable ANY]
s: STRING
jv: detachable JSON_VALUE
do
create jc.make
json.add_converter (jc)
create l.make
s := "foo"
l.force (s)
s := "bar"
l.force (s)
jv := json.value (l)
assert ("jv /= Void", jv /= Void)
if attached jv as l_jv then
s := jv.representation
l2 ?= json.object (jv, "LINKED_LIST")
assert ("l2 /= Void", l2 /= Void)
l.force ("foo")
l.force ("bar")
if attached json.value (l) as l_value then
s := l_value.representation
assert ("JSON array converted to LINKED_LIST", attached {LINKED_LIST [detachable ANY]} json.object (l_value, "LINKED_LIST"))
else
assert ("LINKED_LIST converted to a JSON value", False)
end
end
test_hash_table_converter
-- Convert a hash table to a json value and
-- convert this one to a hash table.
local
tc: JSON_HASH_TABLE_CONVERTER
t: HASH_TABLE [STRING, STRING]
t2: detachable HASH_TABLE [ANY, HASHABLE]
s: STRING
ucs_key, ucs_value: detachable STRING_32
jv: detachable JSON_VALUE
l_ucs_key: detachable STRING_32
do
create tc.make
json.add_converter (tc)
create t.make (2)
t.put ("foo", "1")
t.put ("bar", "2")
jv := json.value (t)
assert ("jv /= Void", jv /= Void)
if attached jv as l_jv then
s := l_jv.representation
t2 ?= json.object (l_jv, "HASH_TABLE")
assert ("t2 /= Void", t2 /= Void)
if attached json.value (t) as l_value then
s := l_value.representation
if attached {HASH_TABLE [ANY, HASHABLE]} json.object (l_value, "HASH_TABLE") as t2 then
create l_ucs_key.make_from_string ("1")
if attached {STRING_32} t2 [l_ucs_key] as l_ucs_value then
assert ("ucs_value.string.is_equal (%"foo%")", l_ucs_value.same_string_general ("foo"))
else
assert ("ucs_value /= Void", False)
end
create ucs_key.make_from_string ("1")
if attached t2 as l_t2 then
ucs_value ?= t2 @ ucs_key
assert ("ucs_value /= Void", ucs_value /= Void)
if attached ucs_value as l_ucs_value then
assert ("ucs_value.string.is_equal (%"foo%")", l_ucs_value.string.is_equal ("foo"))
create l_ucs_key.make_from_string ("2")
if attached {STRING_32} t2 [l_ucs_key] as l_ucs_value then
assert ("ucs_value.string.is_equal (%"bar%")", l_ucs_value.same_string_general ("bar"))
else
assert ("ucs_value /= Void", False)
end
create ucs_key.make_from_string ("2")
ucs_value ?= t2 @ ucs_key
assert ("ucs_value /= Void", ucs_value /= Void)
if attached ucs_value as l_ucs_value then
assert ("ucs_value.string.is_equal (%"bar%")", l_ucs_value.string.is_equal ("bar"))
else
assert ("JSON object converted to HASH_TABLE", False);
end
else
assert ("HASH_TABLE converted to a JSON value", False)
end
end

View File

@@ -1,10 +1,19 @@
class TEST_JSON_CORE
class
TEST_JSON_CORE
inherit
SHARED_EJSON
rename default_create as shared_default_create end
undefine
default_create
end
EQA_TEST_SET
select default_create end
JSON_PARSER_ACCESS
undefine
default_create
end
feature -- Test
@@ -31,15 +40,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_8 since the value is 42
jrep := "42"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
assert ("l_i8 = 42", l_i8 = 42)
else
assert ("json.object (jn, Void) is a INTEGER_8", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -66,15 +75,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_8 since the value is 42
jrep := "42"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
assert ("l_i8 = 42", l_i8 = 42)
else
assert ("json.object (jn, Void) is a INTEGER_8", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -101,15 +110,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_16 since the value is 300
jrep := "300"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {INTEGER_16} json.object (jn, Void) as l_i16 then
assert ("l_i16 = 300", l_i16 = 300)
else
assert ("json.object (jn, Void) is a INTEGER_16", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -136,15 +145,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_32 since the value is 100000
jrep := "100000"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {INTEGER_32} json.object (jn, Void) as l_i32 then
assert ("l_i32 = 100000", l_i32 = 100000)
else
assert ("json.object (jn, Void) is a INTEGER_32", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -171,15 +180,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_32 since the value is 42949672960
jrep := "42949672960"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {INTEGER_64} json.object (jn, Void) as l_i64 then
assert ("l_i64 = 42949672960", l_i64 = 42949672960)
else
assert ("json.object (jn, Void) is a INTEGER_64", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -206,15 +215,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_16 since the value is 200
jrep := "200"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {INTEGER_16} json.object (jn, Void) as i16 then
assert ("i16 = 200", i16 = 200)
else
assert ("json.object (jn, Void) is an INTEGER_16", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -241,15 +250,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_32 since the value is 32768
jrep := "32768"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {INTEGER_32} json.object (jn, Void) as i32 then
assert ("i32 = 32768", i32 = 32768)
else
assert ("json.object (jn, Void) is a INTEGER_32", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -276,15 +285,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_64 since the value is 2147483648
jrep := "2147483648"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {INTEGER_64} json.object (jn, Void) as i64 then
assert ("i64 = 2147483648", i64 = 2147483648)
else
assert ("json.object (jn, Void) is a INTEGER_64", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -311,15 +320,15 @@ feature -- Test
-- that can represent the value of the JSON number, in this case
-- we know it is INTEGER_32 since the value is 42949672960
jrep := "9223372036854775808" -- 1 higher than largest positive number that can be represented by INTEGER 64
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {NATURAL_64} json.object (jn, Void) as l_n64 then
assert ("l_n64 = 9223372036854775808", l_n64 = 9223372036854775808)
else
assert ("json.object (jn, Void) is a NATURAL_64", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -345,15 +354,15 @@ feature -- Test
-- Note: The JSON_FACTORY will always return a REAL_64 if the value
-- of the JSON number is a floating point number
jrep := "3.14"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {REAL_64} json.object (jn, Void) as r64 then
assert ("3.14 <= r64 and r64 <= 3.141", 3.14 <= r64 and r64 <= 3.141)
else
assert ("json.object (jn, Void) is a REAL_64", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -377,15 +386,15 @@ feature -- Test
-- JSON representation -> JSON value -> Eiffel value
jrep := "3.1400001049041748"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {REAL_64} json.object (l_jn, Void) as r64 then
assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748)
else
assert ("json.object (l_jn, Void) is a REAL_64", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -410,15 +419,15 @@ feature -- Test
-- JSON representation -> JSON value -> Eiffel value
jrep := "3.1415926535897931"
create parser.make_parser (jrep)
if attached {JSON_NUMBER} parser.parse as l_jn then
create parser.make_with_string (jrep)
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
if attached {REAL_64} json.object (jn, Void) as l_r64 then
assert ("l_r64 = 3.1415926535897931", l_r64 = 3.1415926535897931)
else
assert ("json.object (jn, Void) is a REAL_64", False)
end
else
assert ("parser.parse is a JSON_NUMBER", False)
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
end
end
@@ -430,7 +439,7 @@ feature -- Test
do
-- Eiffel value -> JSON value -> JSON representation
b := True
create jb.make_boolean (b)
create jb.make (b)
assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true"))
-- Eiffel value -> JSON value -> JSON representation with factory
if attached {JSON_BOOLEAN} json.value (b) as l_jb then
@@ -440,20 +449,20 @@ feature -- Test
end
-- JSON representation -> JSON value -> Eiffel value
create parser.make_parser ("true")
if attached {JSON_BOOLEAN} parser.parse as l_jb then
create parser.make_with_string ("true")
if attached {JSON_BOOLEAN} parser.next_parsed_json_value as l_jb then
if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
assert ("l_b = True", l_b = True)
else
assert ("json.object (l_jb, Void) is BOOLEAN", False)
end
else
assert ("parser.parse is a JSON_BOOLEAN", False)
assert ("parser.next_parsed_json_value is a JSON_BOOLEAN", False)
end
-- Eiffel value -> JSON value -> JSON representation
b := False
create jb.make_boolean (b)
create jb.make (b)
assert ("jb.representation.same_string (%"false%")", jb.representation.same_string ("false"))
-- Eiffel value -> JSON value -> JSON representation with factory
if attached {JSON_BOOLEAN} json.value (b) as l_jb then
@@ -463,78 +472,72 @@ feature -- Test
end
-- JSON representation -> JSON value -> Eiffel value
create parser.make_parser ("false")
if attached {JSON_BOOLEAN} parser.parse as l_jb then
create parser.make_with_string ("false")
if attached {JSON_BOOLEAN} parser.next_parsed_json_value as l_jb then
if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
assert ("l_b = False", l_b = False)
else
assert ("json.object (l_jb, Void) is a BOOLEAN", False)
end
else
assert ("parser.parse is a JSON_BOOLEAN", False)
assert ("parser.next_parsed_json_value is a JSON_BOOLEAN", False)
end
end
test_json_null
local
a: detachable ANY
dummy_object: STRING
jn: detachable JSON_NULL
jrep: STRING
jn: JSON_NULL
parser: JSON_PARSER
do
-- Eiffel value -> JSON value -> JSON representation
create jn
assert ("jn /= Void", jn /= Void)
assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal ("null"))
jrep := "null"
assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal (jrep))
-- Eiffel value -> JSON value -> JSON representation with factory
jn ?= json.value (Void)
assert ("jn /= Void", jn /= Void)
if attached jn as l_jn then
assert ("jn.representation.is_equal (%"null%")", l_jn.representation.is_equal ("null"))
if attached {JSON_NULL} json.value (Void) as l_json_null then
assert ("jn.representation.is_equal (%"null%")", l_json_null.representation.is_equal ("null"))
else
assert ("json.value (Void) /= Void", False)
end
-- JSON representation -> JSON value -> Eiffel value
jrep := "null"
create parser.make_parser (jrep)
jn := Void
jn ?= parser.parse
assert ("jn /= Void", jn /= Void)
create dummy_object.make_empty
a := dummy_object
a ?= json.object (jn, Void)
assert ("a = Void", a = Void)
create parser.make_with_string (jrep)
if attached parser.next_parsed_json_value as l_json_null then
assert ("a = Void", json.object (l_json_null, Void) = Void)
else
assert ("parser.next_parsed_json_value /= Void", False)
end
end
test_json_string_and_character
local
c: CHARACTER
js: detachable JSON_STRING
jrep: STRING
js: JSON_STRING
parser: JSON_PARSER
do
c := 'a'
-- Eiffel value -> JSON value -> JSON representation
create js.make_json (c.out)
assert ("js /= Void", js /= Void)
create js.make_from_string (c.out)
assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%""))
-- Eiffel value -> JSON value -> JSON representation with factory
js ?= json.value (c)
assert ("js /= Void", js /= Void)
if attached js as l_js then
assert ("js.representation.is_equal (%"%"a%"%")", l_js.representation.is_equal ("%"a%""))
if attached {JSON_STRING} json.value (c) as l_json_str then
assert ("js.representation.is_equal (%"%"a%"%")", l_json_str.representation.is_equal ("%"a%""))
else
assert ("json.value (c) /= Void", False)
end
-- JSON representation -> JSON value -> Eiffel value
jrep := "%"a%""
create parser.make_parser (jrep)
js := Void
js ?= parser.parse
assert ("js /= Void", js /= Void)
if attached {STRING_32} json.object (js, Void) as ucs then
create parser.make_with_string (jrep)
if attached {JSON_STRING} parser.next_parsed_json_value as l_json_str then
if attached {STRING_32} json.object (l_json_str, Void) as ucs then
assert ("ucs.string.is_equal (%"a%")", ucs.string.is_equal ("a"))
end
else
assert ("parser.next_parsed_json_value /= Void", False)
end
end
test_json_string_and_string
@@ -545,25 +548,26 @@ feature -- Test
parser: JSON_PARSER
do
s := "foobar"
jrep := "%"foobar%""
-- Eiffel value -> JSON value -> JSON representation
create js.make_json (s)
assert ("js /= Void", js /= Void)
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
create js.make_from_string (s)
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep))
-- Eiffel value -> JSON value -> JSON representation with factory
js ?= json.value (s)
assert ("js /= Void", js /= Void)
if attached js as l_js then
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
if attached {JSON_STRING} json.value (s) as l_js then
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep))
else
assert ("json.value (s) /= Void", False)
end
-- JSON representation -> JSON value -> Eiffel value
jrep := "%"foobar%""
create parser.make_parser (jrep)
js := Void
js ?= parser.parse
assert ("js /= Void", js /= Void)
if attached {STRING_32} json.object (js, Void) as l_ucs then
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
create parser.make_with_string (jrep)
if attached {JSON_STRING} parser.next_parsed_json_value as l_js then
if attached {STRING_32} json.object (l_js, Void) as l_ucs then
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal (s))
end
else
assert ("parser.next_parsed_json_value /= Void", False)
end
end
@@ -571,31 +575,34 @@ feature -- Test
local
js: detachable JSON_STRING
ucs: detachable STRING_32
jrep: STRING
jrep, s: STRING
parser: JSON_PARSER
do
create ucs.make_from_string ("foobar")
s := "foobar"
jrep := "%"foobar%""
create ucs.make_from_string (s)
-- Eiffel value -> JSON value -> JSON representation
create js.make_json (ucs)
assert ("js /= Void", js /= Void)
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
create js.make_from_string (ucs)
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep))
-- Eiffel value -> JSON value -> JSON representation with factory
js ?= json.value (ucs)
assert ("js /= Void", js /= Void)
if attached js as l_js then
assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal ("%"foobar%""))
if attached {JSON_STRING} json.value (ucs) as l_js then
assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal (jrep))
else
assert ("json.value (ucs) /= Void", False)
end
-- JSON representation -> JSON value -> Eiffel value
jrep := "%"foobar%""
create parser.make_parser (jrep)
js := Void
js ?= parser.parse
assert ("js /= Void", js /= Void)
ucs := Void
ucs ?= json.object (js, Void)
if attached ucs as l_ucs then
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
create parser.make_with_string (jrep)
if attached {JSON_STRING} parser.next_parsed_json_value as l_js then
if attached {STRING_32} json.object (l_js, Void) as l_ucs then
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal (s))
else
assert ("json.object (js, Void) /= Void", False)
end
else
assert ("parser.next_parsed_json_value /= Void", False)
end
end
@@ -603,52 +610,103 @@ feature -- Test
local
js: detachable JSON_STRING
s: detachable STRING_8
ucs: detachable STRING_32
jrep: STRING
parser: JSON_PARSER
do
jrep := "%"foo\\bar%""
create s.make_from_string ("foo\bar")
create js.make_json (s)
assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string ("%"foo\\bar%""))
create js.make_from_string (s)
assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string (jrep))
-- Eiffel value -> JSON value -> JSON representation with factory
js ?= json.value (s)
assert ("js /= Void", js /= Void)
if js /= Void then
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.same_string ("%"foo\\bar%""))
if attached {JSON_STRING} json.value (s) as l_js then
assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.same_string (jrep))
else
assert ("json.value (s) /= Void", False)
end
-- JSON representation -> JSON value -> Eiffel value
jrep := "%"foo\\bar%""
create parser.make_parser (jrep)
js ?= parser.parse
assert ("js /= Void", js /= Void)
ucs ?= json.object (js, Void)
if ucs /= Void then
assert ("ucs.same_string (%"foo\bar%")", ucs.same_string ("foo\bar"))
create parser.make_with_string (jrep)
if attached {JSON_STRING} parser.next_parsed_json_value as l_js then
if attached {STRING_32} json.object (l_js, Void) as l_ucs then
assert ("ucs.same_string (%"foo\bar%")", l_ucs.same_string ("foo\bar"))
end
else
assert ("parser.next_parsed_json_value /= Void", False)
end
jrep := "%"foo\\bar%""
create parser.make_parser (jrep)
if attached {JSON_STRING} parser.parse as jstring then
create parser.make_with_string (jrep)
if attached {JSON_STRING} parser.next_parsed_json_value as jstring then
assert ("unescaped string %"foo\\bar%" to %"foo\bar%"", jstring.unescaped_string_8.same_string ("foo\bar"))
else
assert ("parser.next_parsed_json_value /= Void", False)
end
create js.make_json_from_string_32 ({STRING_32}"%/20320/%/22909/")
create js.make_from_string_32 ({STRING_32} "你好")
assert ("escaping unicode string32 %"%%/20320/%%/22909/%" %"\u4F60\u597D%"", js.item.same_string ("\u4F60\u597D"))
jrep := "%"\u4F60\u597D%"" --| Ni hao
create parser.make_parser (jrep)
if attached {JSON_STRING} parser.parse as jstring then
assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32}"%/20320/%/22909/"))
create parser.make_with_string (jrep)
if attached {JSON_STRING} parser.next_parsed_json_value as jstring then
assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32} "你好"))
else
assert ("parser.next_parsed_json_value /= Void", False)
end
end
test_json_string_and_special_characters_2
local
js: detachable JSON_STRING
s,j: STRING
do
s := "foo%Tbar"
j := "foo\tbar"
create js.make_from_string (s)
assert ("string %"" + s + "%" to json %"" + j + "%"", js.item.same_string (j))
create js.make_from_escaped_json_string (js.item)
assert ("json %"" + j + "%" to string %"" + s + "%"", js.unescaped_string_8.same_string (s))
s := "tab=%T cr=%R newline=%N backslash=%H slash=/ end"
j := "tab=\t cr=\r newline=\n backslash=\\ slash=/ end"
create js.make_from_string (s)
assert ("string %"" + s + "%" to json %"" + j + "%"", js.item.same_string (j))
create js.make_from_escaped_json_string (js.item)
assert ("json %"" + j + "%" to string %"" + s + "%"", js.unescaped_string_8.same_string (s))
s := "<script>tab=%T cr=%R newline=%N backslash=%H slash=/ end</script>"
j := "<script>tab=\t cr=\r newline=\n backslash=\\ slash=/ end<\/script>"
create js.make_from_string (s)
assert ("string %"" + s + "%" to json %"" + j + "%"", js.item.same_string (j))
create js.make_from_escaped_json_string (js.item)
assert ("json %"" + j + "%" to string %"" + s + "%"", js.unescaped_string_8.same_string (s))
create js.make_from_escaped_json_string ("tab=\t")
assert ("js.item.same_string (%"tab=\t%")", js.item.same_string ("tab=\t"))
create js.make_from_escaped_json_string (js.item)
assert ("js.item.same_string (%"tab=\t%")", js.item.same_string ("tab=\t"))
-- <\/script>
create js.make_from_escaped_json_string ("<script>tab=\t<\/script>")
assert ("js.item.same_string (%"<script>tab=\t<\/script>%")", js.item.same_string ("<script>tab=\t<\/script>"))
assert ("js.unescaped_string_8.same_string (%"<script>tab=%%T</script>%")", js.unescaped_string_8.same_string ("<script>tab=%T</script>"))
create js.make_from_escaped_json_string (js.item)
assert ("js.item.same_string (%"<script>tab=\t<\/script>%")", js.item.same_string ("<script>tab=\t<\/script>"))
assert ("js.unescaped_string_8.same_string (%"<script>tab=%%T</script>%")", js.unescaped_string_8.same_string ("<script>tab=%T</script>"))
-- </script>
create js.make_from_escaped_json_string ("<script>tab=\t</script>")
assert ("js.item.same_string (%"<script>tab=\t</script>%")", js.item.same_string ("<script>tab=\t</script>"))
assert ("js.unescaped_string_8.same_string (%"<script>tab=%%T</script>%")", js.unescaped_string_8.same_string ("<script>tab=%T</script>"))
create js.make_from_escaped_json_string (js.item)
assert ("js.item.same_string (%"<script>tab=\t<\/script>%")", js.item.same_string ("<script>tab=\t</script>"))
assert ("js.unescaped_string_8.same_string (%"<script>tab=%%T</script>%")", js.unescaped_string_8.same_string ("<script>tab=%T</script>"))
end
test_json_array
local
ll: LINKED_LIST [INTEGER_8]
ll2: detachable LINKED_LIST [detachable ANY]
ja: detachable JSON_ARRAY
jn: JSON_NUMBER
jrep: STRING
@@ -664,7 +722,7 @@ feature -- Test
ll.extend (5)
-- Note: Currently there is no simple way of creating a JSON_ARRAY
-- from an LINKED_LIST.
create ja.make_array
create ja.make (ll.count)
from
ll.start
until
@@ -677,11 +735,10 @@ feature -- Test
assert ("ja /= Void", ja /= Void)
assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", ja.representation.is_equal ("[0,1,1,2,3,5]"))
-- Eiffel value -> JSON value -> JSON representation with factory
ja := Void
ja ?= json.value (ll)
assert ("ja /= Void", ja /= Void)
if attached ja as l_ja then
if attached {JSON_ARRAY} json.value (ll) as l_ja then
assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", l_ja.representation.is_equal ("[0,1,1,2,3,5]"))
else
assert ("json.value (ll) /= Void", False)
end
-- JSON representation -> JSON value -> Eiffel value
@@ -690,23 +747,21 @@ feature -- Test
-- it means we will get an LINKED_LIST [ANY] containing the INTEGER_8
-- values 0, 1, 1, 2, 3, 5
jrep := "[0,1,1,2,3,5]"
create parser.make_parser (jrep)
ja := Void
ja ?= parser.parse
assert ("ja /= Void", ja /= Void)
ll2 ?= json.object (ja, Void)
assert ("ll2 /= Void", ll2 /= Void)
--ll.compare_objects
--ll2.compare_objects
if attached ll2 as l_ll2 then
create parser.make_with_string (jrep)
if attached {JSON_ARRAY} parser.next_parsed_json_value as l_ja then
if attached {LINKED_LIST [detachable ANY]} json.object (ja, Void) as l_ll2 then
assert ("ll2.is_equal (ll)", l_ll2.is_equal (ll))
else
assert ("json.object (ja, Void) /= Void", False)
end
else
assert ("parser.next_parsed_json_value /= Void", False)
end
end
test_json_object
local
t, t2: detachable HASH_TABLE [detachable ANY, STRING_GENERAL]
t: detachable HASH_TABLE [detachable ANY, STRING_GENERAL]
i: INTEGER
ucs_key, ucs: STRING_32
a: ARRAY [INTEGER]
@@ -722,14 +777,14 @@ feature -- Test
-- a HASH_TABLE, so we do it manually.
-- t = {"name": "foobar", "size": 42, "contents", [0, 1, 1, 2, 3, 5]}
create jo.make
create js_key.make_json ("name")
create js.make_json ("foobar")
create js_key.make_from_string ("name")
create js.make_from_string ("foobar")
jo.put (js, js_key)
create js_key.make_json ("size")
create js_key.make_from_string ("size")
create jn.make_integer (42)
jo.put (jn, js_key)
create js_key.make_json ("contents")
create ja.make_array
create js_key.make_from_string ("contents")
create ja.make (6)
create jn.make_integer (0)
ja.add (jn)
create jn.make_integer (1)
@@ -745,6 +800,7 @@ feature -- Test
jo.put (ja, js_key)
assert ("jo /= Void", jo /= Void)
assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"))
-- Eiffel value -> JSON value -> JSON representation with factory
create t.make (3)
create ucs_key.make_from_string ("name")
@@ -756,26 +812,28 @@ feature -- Test
create ucs_key.make_from_string ("contents")
a := <<0, 1, 1, 2, 3, 5>>
t.put (a, ucs_key)
jo := Void
jo ?= json.value (t)
assert ("jo /= Void", jo /= Void)
if attached jo as l_jo then
if attached {JSON_OBJECT} json.value (t) as l_jo then
assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", l_jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"))
end
-- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation
jrep := "{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"
create parser.make_parser (jrep)
jo := Void
jo ?= parser.parse
assert ("jo /= Void", jo /= Void)
t2 ?= json.object (jo, Void)
assert ("t2 /= Void", t2 /= Void)
jo ?= json.value (t2)
assert ("jo /= Void", jo /= Void)
if attached jo as l_jo then
assert ("jrep.is_equal (jo.representation)", jrep.is_equal (jo.representation))
else
assert ("json.value (t) /= Void", False)
end
-- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation
jrep := "{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"
create parser.make_with_string (jrep)
if attached {JSON_OBJECT} parser.next_parsed_json_value as l_jo then
if attached {HASH_TABLE [detachable ANY, STRING_GENERAL]} json.object (l_jo, Void) as l_t2 then
if attached json.value (l_t2) as l_jo_2 then
assert ("jrep.is_equal (jo.representation)", jrep.is_equal (l_jo_2.representation))
else
assert ("json.value (t2) /= Void", False)
end
else
assert ("json.object (jo, Void) /= Void", False)
end
else
assert ("parser.next_parsed_json_value /= Void", jo /= Void)
end
end
test_json_object_hash_code
@@ -802,7 +860,6 @@ feature -- Test
jv := json.value (gv)
else
assert ("exceptions.is_developer_exception", json.is_developer_exception)
-- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert Eiffel object to a JSON_VALUE: OPERATING_ENVIRONMENT"))
end
rescue
exception := True
@@ -813,17 +870,15 @@ feature -- Test
-- Test converting from a JSON value to an Eiffel object based on a
-- class for which no JSON converter has been registered.
local
gv : detachable OPERATING_ENVIRONMENT
gv: detachable ANY
jo: JSON_OBJECT
exception: BOOLEAN
do
if not exception then
create jo.make
gv ?= json.object (jo, "OPERATING_ENVIRONMENT")
gv := json.object (jo, "OPERATING_ENVIRONMENT")
else
assert ("exceptions.is_developer_exception", json.is_developer_exception)
-- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert JSON_VALUE to an Eiffel object: JSON_OBJECT -> OPERATING_ENVIRONMENT"))
end
rescue
exception := True

View File

@@ -1,19 +1,28 @@
class TEST_JSON_CUSTOM_CLASSES
note
description: "Parsing and converter of book collection test."
date: "$Date$"
revision: "$Revision$"
class
TEST_JSON_CUSTOM_CLASSES
inherit
SHARED_EJSON
rename default_create as shared_default_create end
undefine
default_create
end
EQA_TEST_SET
select default_create end
feature -- Test
test_custom_classes
-- Parse JSON representation to JSON_OBJECT and test book collection converter.
local
bc: detachable BOOK_COLLECTION
jbc: JSON_BOOK_CONVERTER
jbcc: JSON_BOOK_COLLECTION_CONVERTER
jac: JSON_AUTHOR_CONVERTER
jo: detachable JSON_OBJECT
parser: JSON_PARSER
jrep: STRING
do
@@ -25,18 +34,19 @@ feature -- Test
json.add_converter (jac)
jrep := "{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"
create parser.make_parser (jrep)
jo := Void
jo ?= parser.parse
assert ("jo /= Void", jo /= Void)
bc := Void
bc ?= json.object (jo, "BOOK_COLLECTION")
assert ("bc /= Void", bc /= Void)
jo ?= json.value (bc)
assert ("jo /= Void", jo /= Void)
if attached jo as l_jo then
assert ("JSON representation is correct", l_jo.representation.same_string ("{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"))
if attached {JSON_OBJECT} parser.parse as l_json_object then
if attached {BOOK_COLLECTION} json.object (l_json_object, "BOOK_COLLECTION") as l_collection then
if attached {JSON_OBJECT} json.value (l_collection) as l_json_object_2 then
assert ("JSON representation is correct", l_json_object_2.representation.same_string (jrep))
else
assert ("BOOK_COLLECTION converted to JSON_OBJECT", False)
end
else
assert ("JSON_OBJECT converted to BOOK_COLLECTION", False)
end
else
assert ("JSON object representation to JSON_OBJECT", False)
end
end
end -- class TEST_JSON_CUSTOM_CLASS

View File

@@ -33,8 +33,8 @@ feature -- Tests Pass
do
if attached json_file_from ("pass1.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("pass1.json",parse_json.is_parsed = True)
parse_json.parse_content
assert ("pass1.json", parse_json.is_valid)
end
end
@@ -45,8 +45,8 @@ feature -- Tests Pass
do
if attached json_file_from ("pass2.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("pass2.json",parse_json.is_parsed = True)
parse_json.parse_content
assert ("pass2.json",parse_json.is_valid)
end
end
@@ -57,8 +57,25 @@ feature -- Tests Pass
do
if attached json_file_from ("pass3.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("pass3.json",parse_json.is_parsed = True)
parse_json.parse_content
assert ("pass3.json",parse_json.is_valid)
end
end
test_json_utf_8_pass1
local
parse_json: like new_json_parser
utf: UTF_CONVERTER
s: READABLE_STRING_32
do
s := {STRING_32} "{ %"nihaoma%": %"你好吗\t?%" }"
parse_json := new_json_parser (utf.string_32_to_utf_8_string_8 (s))
parse_json.parse_content
assert ("utf8.pass1.json", parse_json.is_valid)
if attached {JSON_OBJECT} parse_json.parsed_json_value as jo and then attached {JSON_STRING} jo.item ("nihaoma") as js then
assert ("utf8.nihaoma", js.unescaped_string_32.same_string ({STRING_32} "你好吗%T?"))
else
assert ("utf8.nihaoma", False)
end
end
@@ -70,8 +87,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail1.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail1.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail1.json", parse_json.is_valid = False)
end
end
@@ -82,8 +99,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail2.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail2.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail2.json",parse_json.is_valid = False)
end
end
@@ -94,8 +111,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail3.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail3.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail3.json",parse_json.is_valid = False)
end
end
@@ -106,8 +123,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail4.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail4.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail4.json",parse_json.is_valid = False)
end
end
@@ -118,8 +135,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail5.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail5.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail5.json",parse_json.is_valid = False)
end
end
@@ -131,8 +148,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail6.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail6.json",parse_json.is_parsed = False )
parse_json.parse_content
assert ("fail6.json",parse_json.is_valid = False )
end
end
@@ -143,8 +160,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail7.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail7.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail7.json",parse_json.is_valid = False)
end
end
@@ -155,8 +172,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail8.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail8.json",parse_json.is_parsed = False )
parse_json.parse_content
assert ("fail8.json",parse_json.is_valid = False )
end
end
@@ -168,8 +185,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail9.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail9.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail9.json",parse_json.is_valid = False)
end
end
@@ -181,8 +198,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail10.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail10.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail10.json",parse_json.is_valid = False)
end
end
@@ -193,8 +210,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail11.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail11.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail11.json",parse_json.is_valid = False)
end
end
@@ -205,8 +222,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail12.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail12.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail12.json",parse_json.is_valid = False)
end
end
@@ -217,8 +234,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail13.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail13.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail13.json",parse_json.is_valid = False)
end
end
@@ -229,8 +246,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail14.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail14.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail14.json",parse_json.is_valid = False)
end
end
@@ -241,8 +258,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail15.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail15.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail15.json",parse_json.is_valid = False)
end
end
@@ -253,8 +270,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail16.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail16.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail16.json",parse_json.is_valid = False)
end
end
@@ -265,8 +282,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail17.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail17.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail17.json",parse_json.is_valid = False)
end
end
@@ -277,8 +294,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail18.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail18.json",parse_json.is_parsed = True)
parse_json.parse_content
assert ("fail18.json",parse_json.is_valid = True)
end
end
@@ -289,8 +306,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail19.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail19.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail19.json",parse_json.is_valid = False)
end
end
@@ -301,8 +318,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail20.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail20.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail20.json",parse_json.is_valid = False)
end
end
@@ -313,8 +330,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail21.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail21.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail21.json",parse_json.is_valid = False)
end
end
@@ -326,8 +343,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail22.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail22.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail22.json",parse_json.is_valid = False)
end
end
@@ -338,8 +355,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail23.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail23.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail23.json",parse_json.is_valid = False)
end
end
@@ -350,8 +367,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail24.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail24.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail24.json",parse_json.is_valid = False)
end
end
@@ -362,8 +379,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail25.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail25.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail25.json",parse_json.is_valid = False)
end
end
@@ -375,8 +392,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail26.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail26.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail26.json",parse_json.is_valid = False)
end
end
@@ -388,8 +405,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail27.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail27.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail27.json",parse_json.is_valid = False)
end
end
@@ -401,8 +418,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail28.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail28.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail28.json",parse_json.is_valid = False)
end
end
@@ -414,8 +431,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail29.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail29.json",parse_json.is_parsed = False )
parse_json.parse_content
assert ("fail29.json",parse_json.is_valid = False )
end
end
@@ -427,8 +444,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail30.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail30.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail30.json",parse_json.is_valid = False)
end
end
@@ -439,8 +456,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail31.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail31.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail31.json",parse_json.is_valid = False)
end
end
@@ -451,8 +468,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail32.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail32.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail32.json",parse_json.is_valid = False)
end
end
@@ -463,8 +480,8 @@ feature -- Tests Failures
do
if attached json_file_from ("fail33.json") as json_file then
parse_json := new_json_parser (json_file)
json_value := parse_json.parse_json
assert ("fail33.json",parse_json.is_parsed = False)
parse_json.parse_content
assert ("fail33.json",parse_json.is_valid = False)
end
end
@@ -472,38 +489,42 @@ feature -- JSON_FROM_FILE
file_reader: JSON_FILE_READER
json_value: detachable JSON_VALUE
json_file_from (fn: STRING): detachable STRING
do
Result := file_reader.read_json_from (test_dir + fn)
assert ("File contains json data", Result /= Void)
end
new_json_parser (a_string: STRING): JSON_PARSER
do
create Result.make_parser (a_string)
end
test_dir: STRING
json_file_from (fn: READABLE_STRING_GENERAL): detachable STRING
local
f: RAW_FILE
l_path: PATH
test_dir: PATH
i: INTEGER
do
Result := (create {EXECUTION_ENVIRONMENT}).current_working_directory
Result.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
-- The should looks like
test_dir := (create {EXECUTION_ENVIRONMENT}).current_working_path
l_path := test_dir.extended (fn)
create f.make_with_path (l_path)
if f.exists then
-- Found json file
else
-- before EiffelStudio 7.3 , the current dir of autotest execution was not the parent dir of ecf but something like
-- ..json\test\autotest\test_suite\EIFGENs\test_suite\Testing\execution\TEST_JSON_SUITE.test_json_fail1\..\..\..\..\..\fail1.json
from
i := 5
until
i = 0
loop
Result.append_character ('.')
Result.append_character ('.')
Result.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
test_dir := test_dir.extended ("..")
i := i - 1
end
-- Result := "/home/jvelilla/work/project/Eiffel/ejson_dev/trunk/test/autotest/test_suite/"
l_path := test_dir.extended (fn)
end
create f.make_with_path (l_path)
if f.exists then
Result := file_reader.read_json_from (l_path.name)
end
assert ("File contains json data", Result /= Void)
end
new_json_parser (a_string: STRING): JSON_PARSER
do
create Result.make_with_string (a_string)
end
invariant

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="test_suite" uuid="EA141B17-6A21-4781-8B5F-E9939BAE968A">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="test_suite" uuid="EA141B17-6A21-4781-8B5F-E9939BAE968A">
<target name="test_suite">
<root cluster="test_suite" class="APPLICATION" feature="make"/>
<file_rule>
@@ -7,11 +7,11 @@
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="standard">
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="standard">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="json" location="..\..\..\library\json-safe.ecf"/>
<library name="json" location="..\..\..\library\json-safe.ecf" readonly="false"/>
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
<cluster name="test_suite" location=".\" recursive="true"/>
</target>

View File

133
doc/wiki/Deployment.md Normal file
View File

@@ -0,0 +1,133 @@
EWF Deployment
==============
##Apache on Windows
###Apache Install
- Check the correct version (Win 32 or Win64)
- Apache Version: Apache 2.4.4
- Windows: http://www.apachelounge.com/download/
###Deploying EWF CGI
####CGI overview
> A new process is started for each HTTP request. So if there are N request to the same CGI
> program, the code of the CGI program is loaded into memory N times.
> When a CGI program finished handling a request, the program terminates
1. Build EWF application.
```
ec -config app.ecf -target app_cgi -finalize -c_compile -project_path .
Note: change app.ecf and target app_cgi based on your own configuration.
```
2. Copy the generated exe file and the www content.
```
Copy the app.exe and the folder www into a folder served by apache2, for example under
<APACHE_PATH>/htdocs
<APACHE_PATH> = path to your apache installation
Edit httpd.conf under c:/<APACHE_PATH>/conf
DocumentRoot "c:/<APACHE_PATH>/htdocs"
<Directory "c:/<APACHE_PATH>/htdocs">
AllowOverride All --
Require all granted -- this is required in Apache 2.4.4
</Directory>
```
3. Check that you have the following modules enabled.
```
LoadModule cgi_module modules/mod_cgi.so
LoadModule rewrite_module modules/mod_rewrite.so
```
*Tip:*
To check the syntax of your httpd.conf file. From command line run the following.
```
$>httpd - t
```
####.htaccess CGI
http://perishablepress.com/stupid-htaccess-trics/
```
Options +ExecCGI +Includes +FollowSymLinks -Indexes
AddHandler cgi-script exe
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ $service [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !$service
RewriteRule ^(.*)$ $service/$1
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule
```
Replace $service with the name of your executable service, for example app_service.exe
##Deploying EWF FCGI
- To deploy FCGI you will need to download the mod_fcgi module.
- You can get it from here http://www.apachelounge.com/download/
###FCGI overview
> FastCGI allows a single, long-running process to handle more than one user request while keeping close to
> the CGI programming model, retaining the simplicity while eliminating the overhead of creating a new
> process for each request. Unlike converting an application to a web server plug-in, FastCGI applications
> remain independent of the web server.
1. Build EWF application
```
ec -config app.ecf -target app_fcgi -finalize -c_compile -project_path .
Note: change app.ecf and target app_fcgi based on your own configuration.
```
2. Copy the generated exe file and the www content
```
Copy the app.exe and the folder "www" into a folder served by apache2, for example under
<APACHE_PATH>/htdocs.
<APACHE_PATH> = path to your apache installation
Edit httpd.conf under c:/<APACHE_PATH>/conf
DocumentRoot "c:/<APACHE_PATH>/htdocs"
<Directory "c:/<APACHE_PATH>/htdocs">
AllowOverride All --
Require all granted -- this is required in Apache 2.4.4
</Directory>
```
Check that you have the following modules enabled.
```
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule fcgid_module modules/mod_fcgid.so
```
By default Apache does not comes with fcgid module, so you will need to
download it, and put the module under Apache2/modules
####.htaccess FCGI
http://perishablepress.com/stupid-htaccess-tricks/
```
Options +ExecCGI +Includes +FollowSymLinks -Indexes
<IfModule mod_fcgid.c>
AddHandler fcgid-script .ews
FcgidWrapper $FULL_PATH/$service .ews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteRule ^$ service.ews [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !service.ews
RewriteRule ^(.*)$ service.ews/$1 RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>
```
Replace $service with the name of your executable $service, for example app_service.exe
You will need to create an service.ews file, this file will be located at the same place where you
copy your app service executable.

View File

@@ -0,0 +1,57 @@
Menu :: [[Doc_Getting_Started.mediawiki|Getting Started]] :: [[Community-collaboration.md|Community]]
= Getting Started =
This page will help you to get started with EWF. We will first see how to install EWF and then how to compile and run the venerable Hello World example.
== Installation ==
=== EiffelStudio 7.2 ===
EWF is already included in EiffelStudio 7.2: you don't have to do anything in this case! This is the recommanded solution if you are a new developer or are new to Eiffel.
=== Other EiffelStudio versions ===
If you have another version of EiffelStudio than 7.2, you have to
* dowload EWF
* create a directory where you will put your custum Eiffel libraries
* extract EWF in the newly created directory
* define the environment variable EIFFEL_LIBRARY to point to the newly created directory
=== Source code ===
The source code is available on Github. You can get it by running the command:
<code>git clone git://github.com/EiffelWebFramework/EWF.git</code>
== Hello World ==
The hello world example is located in the directory $ISE_EIFFEL/contrib/examples/web/ewf/simple. Just double click on the simple.ecf file and select the simple target or if you prefer the command line, run the command:
<code>estudio -config simple.ecf -target simple</code>
Once the project is compiled, we will adapt the root class to point to port number 9090.
'''Note''': By default, the application listens on port 80, which is often already used by standard webservers (Apache, nginx, ...). Moreover, on Linux, ports below 1024 can only be opened by root.
To do this, we will redefine the feature initialize as follows:
class
APPLICATION
inherit
WSF_DEFAULT_SERVICE
redefine
initialize
end
create
make_and_launch
feature {NONE} -- Initialization
initialize
-- Initialize current service
do
set_service_option ("port", 9090)
end
end
After one more compile, you can now launch the application and point your browser to [http://localhost:9090].
You should now see a simple page with Hello World.

View File

@@ -0,0 +1,7 @@
Menu :: [[Doc_Getting_Started.mediawiki|Getting Started]] :: [[community.md|Community]]
= Eiffel Web Framework =
Framework to build web applications in Eiffel
[ [http://github.com/EiffelWebFramework/EWF/zipball/ Download Current] ]
[ [http://github.com/EiffelWebFramework/EWF/zipball/release-0.3 Download v0.3] ]

View File

@@ -1,5 +1,5 @@
- See proposed specifications: [[EWSGI specification| EWSGI-specification]]
- See [[Open questions| EWSGI-open-questions]]
- See proposed specifications: [EWSGI specification](EWSGI-specification.md)
- See [Open questions](EWSGI-Open-Questions.md)
- And below the various proposals and associated decision
----

View File

@@ -4,7 +4,7 @@
## Preface
This specification is a proposition based on recent discussion on the mailing list.
This is work in progress, so far nothing had been decided.
You can find another proposal at http://eiffel.seibostudios.se/wiki/EWSGI , it has common background and goal, however still differ on specific parts.
You can find another proposal at [http://eiffel.seibostudios.se/wiki/EWSGI](http://eiffel.seibostudios.se/wiki/EWSGI) , it has common background and goal, however still differ on specific parts.
The main goal for now is to unified those 2 specifications.
---
@@ -12,7 +12,7 @@ Note the following is work in progress, and reflect a specification proposal, ra
2011-08-01
---
For now, the specification from EWF is done in Eiffel interface
please see: https://github.com/Eiffel-World/Eiffel-Web-Framework/tree/master/library/server/ewsgi/specification
please see: [https://github.com/Eiffel-World/Eiffel-Web-Framework/tree/master/library/server/ewsgi/specification](https://github.com/Eiffel-World/Eiffel-Web-Framework/tree/master/library/server/ewsgi/specification)
WGI_APPLICATION

View File

@@ -1,26 +0,0 @@
# Eiffel-Web-Framework #
## Location ##
The official documentation/wiki is located at https://github.com/EiffelWebFramework/EWF/wiki , if you are visiting a "clone/fork", please always check the [[official wiki|https://github.com/EiffelWebFramework/EWF/wiki]].
## Organization ##
- Mailing list: please visit and subscribe to the mailing list page [[http://groups.google.com/group/eiffel-web-framework]] ![logo](http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif)
- Most of the topics are discussed on the mailing list (google group).
- For time to time we have web meeting, and less frequently physical meetings that occurs usually during other Eiffel related events.
## Documentation ##
- to redo
## Contributions ##
- You want to contribute or follow the progress/discussion, see the [[collaboration page| Community-collaboration]]
- Potential tasks/projects on EWF: [[Projects page| Projects]]
## See also ##
- [[list of tasks, and a potential roadmap| Tasks-Roadmap]]
- [[General source structure of this project| Source-structure]]
- EWSGI: [[Eiffel Web Server Gateway Interface| EWSGI]]
- [[Overview of the server side architecture| Spec-Server-Architecture]]
- This project is also a collection of [[Libraries]] related to the Web
## Note ##
- This wiki needs to be updated, in the meantime, please have a look at the presentation: https://docs.google.com/presentation/pub?id=1GPFv6aHhTjFSLMnlAt-J4WeIHSGfHdB42dQxmOVOH8s&start=false&loop=false&delayms=3000

26
doc/wiki/README.md Normal file
View File

@@ -0,0 +1,26 @@
# Eiffel-Web-Framework #
## Location ##
The official documentation/wiki is located at [https://github.com/EiffelWebFramework/EWF/wiki](https://github.com/EiffelWebFramework/EWF/wiki) , if you are visiting a "clone/fork", please always check the [official wiki](https://github.com/EiffelWebFramework/EWF/wiki).
## Organization ##
- Mailing list: please visit and subscribe to the mailing list page [http://groups.google.com/group/eiffel-web-framework](http://groups.google.com/group/eiffel-web-framework) ![logo](http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif)
- Most of the topics are discussed on the mailing list (google group).
- For time to time we have [web meetings](project/Meetings.md), and less frequently [physical meetings](project/Meetings.md) that occurs usually during other Eiffel related events.
## Documentation ##
- [Documentation](documentation/README.md)
## Contributions ##
- You want to contribute or follow the progress/discussion, see the [collaboration page](community.md)
- Potential tasks/projects on EWF: [Projects page](project/Projects.md)
## See also ##
- [list of tasks, and a potential roadmap](project/Tasks-Roadmap.md)
- [General source structure of this project](Source-structure.md)
- EWSGI: [Eiffel Web Server Gateway Interface](EWSGI/README.md)
- [Overview of the server side architecture](Spec-Server-Architecture.md)
- This project is also a collection of [Libraries](Libraries.md) related to the Web
## Note ##
- This wiki needs to be updated, in the meantime, please have a look at the presentation: [https://docs.google.com/presentation/pub?id=1GPFv6aHhTjFSLMnlAt-J4WeIHSGfHdB42dQxmOVOH8s&start=false&loop=false&delayms=3000](https://docs.google.com/presentation/pub?id=1GPFv6aHhTjFSLMnlAt-J4WeIHSGfHdB42dQxmOVOH8s&start=false&loop=false&delayms=3000)

View File

@@ -1,13 +1,13 @@
This project is a community project
## Mailing list ##
- Google group: http://groups.google.com/group/eiffel-web-framework
- Google group: [http://groups.google.com/group/eiffel-web-framework](http://groups.google.com/group/eiffel-web-framework)
## Materials ##
- wiki: github wiki at https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki
- Shared documents: on google docs at http://goo.gl/M8WLP
- source code: git repository at https://github.com/Eiffel-World/Eiffel-Web-Framework
- Proposal from Paul Cohen for a EWSGI spec at http://eiffel.seibostudios.se/wiki/EWSGI
- wiki: github wiki at [https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki](https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki)
- Shared documents: on google docs at [http://goo.gl/M8WLP](http://goo.gl/M8WLP)
- source code: git repository at [https://github.com/Eiffel-World/Eiffel-Web-Framework](https://github.com/Eiffel-World/Eiffel-Web-Framework)
- Proposal from Paul Cohen for a EWSGI spec at [http://eiffel.seibostudios.se/wiki/EWSGI](http://eiffel.seibostudios.se/wiki/EWSGI)
## Main contributors ##
- **jfiat**: Jocelyn Fiat (Eiffel Software)

View File

@@ -0,0 +1,51 @@
The main goal of the connectors is to let you choose a target at compile time.
This allows you to concentrate on your business during development time and then decide which target you choose at deployment time.
The current connectors are:
* Nino
* FastCGI
* CGI
* OpenShift
The most widely used workflow is to use Nino on your development machine and FastCGI on your production server.
Nino being a web server written entirely in Eiffel, you can inspect your HTTP requests and respones in EiffelStudio which is great during development.
On the other hand, FastCGI is great at handling concurrent requests and coupled with Apache (or another web production server), you don't even need to worry about the lifecyle of your application (creation and destruction) as Apache will do it for you!
Let's now dig into each of the connecters.
# Nino
Nino is a web server entirely written in Eiffel.
The goal of Nino is to provide a simple web server for development (like Java, Python and Ruby provide).
Nino is currently maintained by Javier Velilla and the repository can be found here: https://github.com/jvelilla/EiffelWebNino
# FastCGI
FastCGI is a protocol for interfacing an application server with a web server.
It is an improvement over CGI as FastCGI supports long running processes, i.e. processes than can handle multipe requests during their lifecyle. CGI, on the other hand, launches a new process for every new request which is quite time consuming.
FastCGI is implemented by every major web servers: Apache, IIS, Nginx, ...
We recommend to use FastCGI instead of CGI as it is way more faster.
You can read more about FastCGI here: http://www.fastcgi.com/
# CGI
CGI predates FastCGI and is also a protocol for interfacing an application server with a web server.
His main drawback (and the reason why FastCGI was created) is that it launches a new process for every new request, which is quite time consuming.
We recommend to use FastCGI instead of CGI as it is way more faster.
# OpenShift
OpenShift is a cloud computing platform as a service product from Red Hat.
It basically let's you run your application in the cloud.
More informations are available here: https://www.openshift.com
# Writing your own
It's fairly easy to write your own connector. Just inherit from these classes:
* WGI_CONNECTOR
* WGI_ERROR_STREAM
* WGI_INPUT_STREAM
* WGI_OUTPUT_STREAM
* WSF_SERVICE_LAUNCHER
See WSF_CONNECTOR

View File

@@ -0,0 +1,27 @@
# Introduction
The basic idea of a filter is to pre-process incoming data and post-process outgoing data.
Filters are part of a filter chain, thus following the [chain of responsability design pattern](http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern).
Each filter decides to call the next filter or not.
# Levels
In EWF, there are two levels of filters.
## WSF_FILTER
Typical examples of such filters are: logging, compression, routing (WSF_ROUTING_FILTER), ...
## WSF_FILTER_HANDLER
Handler that can also play the role of a filter.
Typical examples of such filters are: authentication, ...
# References
Filters (also called middelwares) in other environments:
* in Python: http://www.wsgi.org/en/latest/libraries.html
* in Node.js: http://expressjs.com/guide.html#middleware
* in Apache: http://httpd.apache.org/docs/2.2/en/filter.html

View File

@@ -0,0 +1,210 @@
# Current Status
* Official repository: <https://github.com/EiffelWebFramework/EWF>
* Official website: <http://eiffelwebframework.github.io/EWF/getting-started/>
# What is EWF?
Eiffel Web Framework, is mainly a collection of Eiffel libraries designed to be integrated with each other. One benefit is that it supports all core HTTP features, so enable you embrace HTTP as an application protocol to develop web applications. So you do not need to adapt your applications to the web, instead you use the web power. It means you can build different kind of web applications, from Web APIs following the Hypermedia API style (REST style), CRUD web services or just conventional web applications building a session on top of an stateless protocol.
# EWF core/kernel
> The Web Server Foundation (WSF\_) is the core of the framework. It is compliant with the EWSGI interface (WGI\_).
To build a web [service](#service), the framework provides a set of core components to launch the service, for each [request](#request-and-response), access the data, and send the [response](#request-and-response).
The framework also provides a router component to help dispatching the incoming request.
A service can be a web api, a web interface, … what ever run on top of HTTP.
<a name="wiki-service"></a>
<a name="service"></a>
# Service
> see interface: **WSF_SERVICE**
Each incoming http request is processed by the following routine.
> `{WSF_SERVICE}.execute (req: WSF_REQUEST; res: WSF_RESPONSE)`
This is the low level of the framework, at this point, `req` provides access to the query and form parameters, input data, headers, ... as specified by the Common Gateway Interface (CGI).
The response `res` is the interface to send data back to the client.
For convenience, the framework provides richer service interface that handles the most common needs (filter, router, ...).
> [Learn more about service](Service.md)
<a name="wiki-request"></a><a name="wiki-response"></a><a name="wiki-request-and-response"></a>
<a name="request"></a><a name="response"></a><a name="request-and-response"></a>
# Request and Response
> see interface: **WSF_REQUEST** and **WSF_RESPONSE**
Any incoming http request is represented by an new object of type **WSF_REQUEST**.
**WSF_REQUEST** provides access to
+ __meta variables__: CGI variables (coming from the request http header)
+ __query parameters__: from the uri ex: `?q=abc&type=pdf`
+ __input data__: the message of the request, if this is a web form, this is parsed to build the form parameters. It can be retrieved once.
+ __form parameters__: standard parameters from the request input data.
- typically available when a web form is sent using POST as content of type `multipart/form-data` or `application/x-www-form-urlencoded`
- (advanced usage: it is possible to write mime handler that can processed other type of content, even custom format.)
+ __uploaded files__: if files are uploaded, their value will be available from the form parameters, and from the uploaded files as well.
+ __cookies variable__: cookies extracted from the http header.
+ __path parameters__: note this is related to the router and carry the semantic of the mapping (see the section on router )
+ __execution variables__: used by the application to keep value associated with the request.
The **WSF_RESPONSE** represents the communication toward the client, a service need to provide correct headers, and content. For instance the `Content-Type`, and `Content-Length`. It also allows to send data with chunked encoding.
> [Learn more about request](Request.md) and [about response](Response.md)
<a name="wiki-connector"></a>
<a name="connector"></a>
# Connectors:
> see **WGI_CONNECTOR**
Using EWF, your service is built on top of underlying httpd solution/connectors.
Currently 3 main connectors are available:
* __CGI__: following the CGI interface, this is an easy solution to run the service on any platform.
* __libFCGI__: based on the libfcgi solution, this can be used with Apache, IIS, nginx, ...
* __nino__: a standalone server: Eiffel Web Nino allow you to embed a web server anywhere, on any platform without any dependencies on other httpd server.
At compilation time, you can use a default connector (by using the associated default lib), but you can also use a mixed of them and choose which one to execute at runtime.
It is fairly easy to add new connector, it just has to follow the EWSGI interface
> [Learn more about connector](Connector.md)
<a name="wiki-router"></a>
<a name="router"></a>
# Router or Request Dispatcher:
> Routes HTTP requests to the proper execution code
A web application needs to have a clean and elegant URL scheme, and EWF provides a router component to design URLs.
The association between a URL pattern and the code handling the URL request is called a Router mapping in EWF.
EWF provides 3 main kinds of mappings
+ __URI__: any URL with path being the specified uri.
- example: “/users/” redirects any “/users/” and “/users/?query=...”
+ __URI-template__: any URL matching the specified URI-template
- example: “/project/{name}/” redirects any “/project/foo” or “/project/bar”
+ __Starts-with__: any URL starting with the specified path
Note: in the future, a Regular-Expression based kind will be added in the future, and it is possible to use custom mapping on top of EWF.
Code:
router.map ( create {WSF_URI_TEMPLATE_MAPPING}.make (
“/project/{name}”, project_handler)
)
-- And precising the request methods
router.map_with_request_methods ( ... , router.methods_GET_POST)
In the previous code, the `project_handler` is an object conforming to **WSF_HANDLER**, that will process the incoming requests matching URI-template “/project/{name}”.
Usually, the service will inherit from WSF_ROUTED_SERVICE, which has a `router` attribute.
Configuring the URL scheme is done by implementing `{WSF_ROUTED_SERVICE}.setup_router`.
To make life easier, by inheriting from WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE, a few help methods are available to `map` URI template with agent, and so on.
See
+ `map_uri_template (a_tpl: STRING; h: WSF_URI_TEMPLATE_HANDLER)`
+ `map_uri_template_agent (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]])`
+ and same with request methods ...
...
Check WSF_\*_HELPER_FOR_ROUTED_SERVICE for other available helper classes.
How we do that in EWF? : Router with (or without context).
Related code: wsf_router, wsf_router_context
Examples
> [Learn more about router](Router.md)
# EWF components
## URI Handler:
> Parses the details of the URI (scheme, path, query info, etc.) and exposes them for use.
How we do that in EWF?: URI Templates, but we could also use regex.
Related code: uri_template
Examples:
## Mime Parser/ Content Negotiation:
> Handles the details of determining the media type, language, encoding, compression (conneg).
How do we do that in EWF? Content_Negotiation library.
Example
## Request Handler
> target of request dispatcher + uri handler.
Here is where we handle GET, POST PUT, etc.
## Representation Mapping
> Converts stored data into the proper representation for responses and handles incoming representations from requests.
We dont have a representation library, the developer need to do that.
If we want to provide different kind of representations: JSON, XML, HTML, the responsibility is let
to the developer to map their domain to the target representation.
## Http Client:
> A simple library to make requests and handle responses from other http servers.
How we do that in EWF? http client library
examples:
## Authentication/Security:
> Handle different auth models. (Basic, Digest?, OAuth, OpenId)
How we do that in EWF? http_authorization, OpenId, and Cypress
examples.
## Caching:
> Support for Caching and conditional request
How we do that in Eiffel? Policy framework on top of EWF. {{{need_review}}}
examples
## EWF HTML5 Widgets
## EWF policy Framework
## EWF application generators
<a name="wiki-EWSGI"></a>
<a name="EWSGI"></a>
# EWSGI Specification
<a name="wiki-libraries"></a>
<a name="libraries"></a>
# Libraries
External libraries are included, such as Cypress OAuth (Security), HTML parsing library, Template Engine Smarty.
## server
* __ewsgi__: Eiffel Web Server Gateway Interface [read more](../EWSGI/index.md).
* connectors: various web server connectors for EWSGI
* __libfcgi__: Wrapper for libfcgi SDK
* __wsf__: Web Server Framework
* __router__: URL dispatching/routing based on uri, uri_template, or custom [read more](Router.md).
* __filter__: Filter chain [read more](Filter.md).
* __wsf_html__: (html and css) Content generator from the server side.
* CMS example: <https://github.com/EiffelWebFramework/cms/tree/master/example>
## protocol
* __http__: HTTP related classes, constants for status code, content types, ...
* __uri_template__: URI Template library (parsing and expander)
* __content_negotiation__: [CONNEG](Library-conneg.md) library (Content-type Negociation)
## Client
* __http_client__: simple [HTTP client](HTTP-client.library.md) based on cURL
* __Firebase API__: <https://github.com/EiffelWebFramework/Redwood>
## Text
* __encoder__: Various simple encoders: base64, url-encoder, xml entities, html entities
## Utils
* __error__: very simple/basic library to handle error
## Security
* __http_authentication__ (under EWF/library/server/authentication)
* __open_id__ (under EWF/library/security)
* __OAuth__ see <https://github.com/EiffelWebFramework/cypress>

View File

@@ -0,0 +1,9 @@
# Request
The class _WSF_REQUEST_ can be used to access data related to the HTTP request.
**TODO**: describe the request interface
# Response
The class _WSF_RESPONSE_ is the media to send data back to the client.
**TODO**: describe the response interface

View File

@@ -0,0 +1,17 @@
See WSF_REQUEST
## About parameters
Note that by default there is a smart computation for the query/post/... parameters:
for instance
- `q=a&q=b` : will create a **WSF_MULTIPLE_STRING** parameter with name **q** and value `[a,b]`
- `tab[a]=ewf&tab[b]=demo` : will create a **WSF_TABLE** parameter with name **tab** and value `{ "a": "ewf", "b": "demo"}`
- `tab[]=ewf&tab[]=demo` : will create a **WSF_TABLE** parameter with name **tab** and value `{ "1": "ewf", "2": "demo"}`
- `tab[foo]=foo&tab[foo]=bar` : will create a **WSF_TABLE** parameter with name **tab** and value `{ "foo": "bar"}` **WARNING: only the last `tab[foo]` is kept**.
Those rules are applied to query, post, path, .... parameters.
## How to get the input data (i.e entity-body) ?
See `{WSF_REQUEST}.read_input_data_into (buf: STRING)`
## How to get the raw header data (i.e the http header text) ?
See `{WSF_REQUEST}.raw_header_data: detachable READABLE_STRING_32`

View File

@@ -0,0 +1 @@
See WSF_RESPONSE

View File

@@ -0,0 +1,6 @@
The primary goal of the router (class _WSF_ROUTER_) is to dispatch requests according to the request URI.
See WSF_ROUTER
**TODO**: describe the router interface

View File

@@ -0,0 +1,2 @@
EWF Services
> See WSF\_SERVICE

View File

@@ -0,0 +1,26 @@
# Using the policy driven framework
## Introduction
The aim of the policy-driven framework is to allow authors of web-servers to concentrate on the business logic (e.g., in the case of a GET request, generating the content), without having to worry about the details of the HTTP protocol (such as headers and response codes). However, there are so many possibilities in the HTTP protocol, that it is impossible to correctly guess what to do in all cases. Therefore the author has to supply policy decisions to the framework, in areas such as caching decisions. These are implemented as a set of deferred classes for which the author needs to provide effective implementations.
We aim to provide unconditional compliance [See HTTP/1.1 specification](http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html#sec1) for you. Note that byte-ranges are not yet supported.
## Mapping the URI space
The authors first task is to decide which URIs the server will respond to (we do this using [URI templates](http://tools.ietf.org/html/rfc6570) ) and which methods are supported for each template.This is done in the class that that defines the service (which is often the root class for the application). This class must be a descendant of WSF_ROUTED_SKELETON_SERVICE. Throughout this tutorial, we will refer to the restbucksCRUD example application, which can be found in the EWF distribution in the examples directory. It's root class, RESTBUCKS_SERVER, inherits from WSF_ROUTED_SKELETON_SERVICE, as well as WSF_DEFAULT_SERVICE. The latter class means that you must specify in the ECF which connector you will use by default.This means you can easily change connectors just by changing the ECF and recompiling.
### Declaring your URI templates
In order to map your URI space to handlers (which you will write), you need to implement the routine setup_router. You can see in the example that the ORDER_HANDLER handler is associated with two URI templates. The URI /order is associated with the POST method (only). Any requests to /order with the GET method (or any other method) will result in an automatically generated compliant response being sent on your behalf to the client. The other principle methods (you get compliant responses to the HEAD method for free whenever you allow the GET method) are associated with the URI template /order/{orderid}. Here, orderid is a template variable. It's value for any given request is provided to your application as {WSF_REQUEST}.path_parameter ("orderid"). If the client passes a URI of /order/21, then you will see the value 21. If the client passes /order/fred, you will see the value fred. But if the client passes /order/21/new, he will see a compliant error response generated by the framework.
## Declaring your policy in responding to OPTIONS
WSF_ROUTED_SKELETON_SERVICE inherits from WSF_SYSTEM_OPTIONS_ACCESS_POLICY. This policy declares that the framework will provide a compliant default response to OPTIONS * requests. If you prefer to not respond to OPTIONS * requests (and I am doubtful if it is fully compliant to make that choice), then you can redefine
is_system_options_forbidden.
## Declaring your policy on requiring use of a proxy server
WSF_ROUTED_SKELETON_SERVICE also inherits from WSF_PROXY_USE_POLICY. This determines if the server will require clients to use a proxy server. By default, it will do so for HTTP/1.0 clients. This is a sensible default, as the framework assumes an HTTP/1.1 client throughout. If you are sure that you will only ever have HTTP/1.1 clients, then you can instead inherit from WSF_NO_PROXY_POLICY, as RESTBUCKS_SERVER does. If not, then you need to implement proxy_server.
Next you have to [write your handler(s)](Writing-the-handlers.md)

View File

@@ -0,0 +1,3 @@
# Implementing routines in WSF_OPTIONS_POLICY
This class provides a default response to OPTIONS requests other than OPTIONS *. So you don't have to do anything. The default response just includes the mandatory Allow headers for all the methods that are allowed for the request URI. if you want to include a body text, or additional header, then you should redefine this routine.

View File

@@ -0,0 +1,223 @@
# Writing the handlers
Now you have to implement each handler. You need to inherit from WSF_SKELETON_HANDLER (as ORDER_HANDLER does). This involves implementing a lot of deferred routines. There are other routines for which default implementations are provided, which you might want to override. This applies to both routines defined in this class, and those declared in the three policy classes from which it inherits.
## Communicating between routines
Depending upon the connector (Nino, CGI, FastCGI etc.) that you are using, your handler may be invoked concurrently for multiple requests. Therefore it is unsafe to save state in normal attributes. WSF_REQUEST has a pair of getter/setter routines, execution_variable/set_execution_variable, which you can use for this purpose.
Internally, the framework uses the following execution variable names, so you must avoid them:
1. REQUEST_ENTITY
1. NEGOTIATED_LANGUAGE
1. NEGOTIATED_CHARSET
1. NEGOTIATED_MEDIA_TYPE
1. NEGOTIATED_ENCODING
1. NEGOTIATED_HTTP_HEADER
1. CONFLICT_CHECK_CODE
1. CONTENT_CHECK_CODE
1. REQUEST_CHECK_CODE
The first one makes the request entity from a PULL or POST request available to your routines.
The next four make the results of content negotiation available to your routines. The sixth one makes an HTTP_HEADER available to your routines. You should use this rather than create your own, as it may contain a **Vary** header as a by-product of content negotiation.
The last three are for reporting the result from check_conflict, check_content and check_request.
All names are defined as constants in WSF_SKELETON_HANDLER, to make it easier for you to refer to them.
## Implementing the routines declared directly in WSF_SKELETON_HANDLER
### check_resource_exists
Here you check for the existence of the resource named by the request URI. If it does, then you need to call set_resource_exists on the helper argument.
Note that if you support multiple representations through content negotiation, then etags are dependent upon
the selected variant. If you support etags, then you will need to make the response entity available at this point, rather than in ensure_content_available.
### is_chunking
HTTP/1.1 supports streaming responses (and providing you have configured your server to use a proxy server in WSF_PROXY_USE_POLICY, this framework guarantees you have an HTTP/1.1 client to deal with). It is up to you whether or not you choose to make use of it. If so, then you have to serve the response one chunk at a time (but you could generate it all at once, and slice it up as you go). In this routine you just say whether or not you will be doing this. So the framework n=knows which other routines to call.
Currently we only support chunking for GET or HEAD routines. This might change in the future, so if you intend to return True, you should call req.is_get_head_request_method.
Note that currently this framework does not support writing a trailer.
### includes_response_entity
The response to a DELETE, PUT or POST will include HTTP headers. It may or may not include a body. It is up to you, and this is where you tell the framework.
### conneg
[The HTTP/1.1 specification](http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1) defines server-driven content negotiation. Based on the Accept* headers in the request, we can determine whether we have a format for the response entity that is acceptable to the client. You need to indicate what formats you support. The framework does the rest. Normally you will have the same options for all requests, in which case you can use a once object.
### mime_types_supported
Here you need to indicate which media types you support for responses. One of the entries must be passed to the creation routine for conneg.
### languages_supported
Here you need to indicate which languages you support for responses. One of the entries must be passed to the creation routine for conneg.
### charsets_supported
Here you need to indicate which character sets you support for responses. One of the entries must be passed to the creation routine for conneg.
### encodings_supported
Here you need to indicate which compression encodings you support for responses. One of the entries must be passed to the creation routine for conneg.
### additional_variant_headers
The framework will write a Vary header if conneg indicates that different formats are supported. This warns caches that they may not be able to use a cached response if the Accept* headers in the request differ. If the author knows that the response may be affected by other request headers in addition to these, then they must be indicated here, so they can be included in a Vary header with the response.
### predictable_response
If the response may vary in other ways not predictable from the request headers, then redefine this routine to return True. In that case we will generate a Vary: * header to inform the cache that the response is not necessarily repeatable.
### matching_etag
An **ETag** header is a kind of message digest. Clients can use etags to avoid re-fetching responses for unchanged resources, or to avoid updating a resource that may have changed since the client last updated it.
You must implement this routine to test for matches **if and only if** you return non-Void responses for the etag routine.
Note that if you support multiple representations through content negotiation, then etags are dependent upon
the selected variant. Therefore you will need to have the response entity available for this routine. This can be done in check_resource_exists.
### etag
You are strongly encouraged to return non-Void for this routine. See [Validation Model](http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3) for more details.
Note that if you support multiple representations through content negotiation, then etags are dependent upon
the selected variant. Therefore you will need to have the response entity available for this routine. This can be done in check_resource_exists.
### modified_since
You need to implement this. If you do not have information about when a resource was last modified, then return True as a precaution. Of course, you return false for a static resource.
### treat_as_moved_permanently
This routine when a PUT request is made to a resource that does not exist. See [PUT](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6) in the HTTP/1.1 specification for why you might want to return zero.
### allow_post_to_missing_resource
POST requests are normally made to an existing entity. However it is possible to create new resources using a POST, if the server allows it. This is where you make that decision.
If you return True, and the resource is created, a 201 Created response will be returned.
### content_length
If you are not streaming the result, the the HTTP protocol requires that the length of the entity is known. You need to implement this routine to provide that information.
### finished
If you are streaming the response, then you need to tell the framework when the last chunk has been sent.
To implement this routine, you will probably need to call req.set_execution_variable (some-name, True) in ensure_content_avaiable and generate_next_chunk, and call attached {BOOLEAN} req.execution_variable (some-name) in this routine.
### description
This is for the automatically generated documentation that the framework will generate in response to a request that you have not mapped into an handler.
### delete
This routine is for carrying out a DELETE request to a resource. If it is valid to delete the named resource, then you should either go ahead and do it, or queue a deletion request somewhere (if you do that then you will probably need to call req.set_execution_variable (some-name-or-other, True). Otherwise you should call req.error_handler.add_custom_error to explain why the DELETE could not proceed (you should also do this if the attempt to delete the resource fails).
Of course, if you have not mapped any DELETE requests to the URI space of this handler, then you can just do nothing.
### delete_queued
If in the delete routine, you elected to queue the request, then you need to return True here. You will probably need to check the execution variable you set in the delete routine.
### ensure_content_available
This routine is called for GET and DELETE (when a entity is provided in the response) processing. It's purpose is to make the text of the entity (body of the response) available for future routines (if is_chunking is true, then only the first chunk needs to be made available, although if you only serve, as opposed to generate, the result in chunks, then you will make the entire entity available here). This is necessary so that we can compute the length before we start to serve the response. You would normally save it in an execution variable on the request object (as ORDER_HANDLER does). Note that this usage of execution variables ensures your routines can successfully cope with simultaneous requests. If you encounter a problem generating the content, then add an error to req.error_handler.
As well as the request object, we provide the results of content negotiation, so you can generate the entity in the agreed format. If you only support one format (i.e. all of mime_types_supported, charsets_supported, encodings_supported and languages_supported are one-element lists), then you are guaranteed that this is what you are being asked for, and so you can ignore them.
Note that if you support multiple representations through content negotiation, then etags are dependent upon
the selected variant. Therefore you will need to have the response entity available for this routine. In such cases, this will have to be done in check_resource_exists, rather than here, as this routine is called later on.
### content
When not streaming, this routine provides the entity to the framework (for GET or DELETE). Normally you would just access the execution variable that you set in ensure_content_available. Again, the results of content negotiation are made available, but you probably don't need them at this stage. If you only stream responses (for GET), and if you don't support DELETE, then you don't need to do anything here.
### generate_next_chunk
When streaming the response, this routine is called to enable you to generate chunks beyond the first, so that you can incrementally generate the response entity. If you generated the entire response entity in
ensure_content_available, then you do nothing here. Otherwise, you will generate the next chunk, and save it in the same execution variable that you use in ensure_content_available (or add an error to req.error_handler). If you don't support streaming, then you don't need to do anything here.
### next_chunk
When streaming the response, the framework calls this routine to provides the contents of each generated chunk. If you generated the entire response entity in ensure_content_available, then you need to slice it in this routine (you will have to keep track of where you are with execution variables). If instead you generate the response incrementally, then your task is much easier - you just access the execution variable saved in ensure_content_available/generate_next_chunk.
As in all these content-serving routines, we provide the results of content negotiation. This might be necessary, for instance, if you were compressing an incrementally generated response (it might be more convenient to do the compression here rather than in both ensure_content_available and generate_next_chunk).
### read_entity
This is called for PUT and POST processing, to read the entity provided in the request. A default implementation is provided. This assumes that no decoding (e.g. decompression or character set conversion) is necessary. And it saves it in the execution variable REQUEST_ENTITY.
Currently the framework provides very little support for PUT and POST requests (so you may well need to redefine this routine). There are several reasons for this:
1. I personally don't have much experience with PUT and POST.
1. It has taken a long time to develop this framework, and to some extent I was working in the dark (I couldn't check what I was doing until the entire framework was written - it wouldn't even compile before then).
1. The idea for the framework came from a code review process on servers I had written for the company that I work for. I had acquired a lot of knowledge of the HTTP protocol in the process, and some of it showed in the code that I had written. It was thought that it would be a good idea if this knowledge were encapsulated in Eiffel, so other developers would be able to write servers without such knowledge. So this framework has been developed in company time. However, at present, we are only using GET requests.
Experience with converting the restbucksCRUD example to use the framework, shows that it is certainly possible to do POST and PUT processing with it. But enhancements are needed, especially in the area of decoding the request entity.
### is_entity_too_large
If your application has limits on the size of entities that it can store, then you implement them here.
### check_content_headers
This is called after is_entity_too_large returns False. You are supposed to check the following request headers, and take any appropriate actions (such as setting an error, decompression the entity, or converting it to a different character set):
* Content-Encoding
* Content-Language
* Content-MD5
* Content-Range
* Content-Type
At the moment, your duty is to set the execution variable CONTENT_CHECK_CODE to zero, or an HTTP error status code. A future enhancement of the framework might be to provide more support for this.
### content_check_code
This simply accesses the execution variable CONTENT_CHECK_CODE set in check_content_headers. if you want to use some other mechanism, then you can redefine this routine.
### create_resource
This routine is called when a PUT request is made with a URI that refers to a resource that does not exist (PUT is normally used for updating an existing resource), and you have already decided to allow this.
In this routine you have the responsibilities of:
1. Creating the resource using the entity in REQUEST_ENTITY (or some decoded version that you have stored elsewhere).
1. Writing the entire response yourself (as I said before, support for PUT and POST processing is poor at present), including setting the status code of 201 Created or 303 See Other or 500 Internal server error).
### append_resource
This routine is called for POST requests on an existing resource (normal usage).
In this routine you have the responsibilities of:
1. Storing the entity from REQUEST_ENTITY (or some decoded version that you have stored elsewhere), or whatever other action is appropriate for the semantics of POST requests to this URI.
1. Writing the entire response yourself (as I said before, support for PUT and POST processing is poor at present), including setting the status code of 200 OK, 204 No Content, 303 See Other or 500 Internal server error).
### check_conflict
This is called for a normal (updating) PUT request. You have to check to see if the current state of the resource makes updating impossible. If so, then you need to write the entire response with a status code of 409 Conflict, and set the execution variable CONFLICT_CHECK_CODE to 409.
Otherwise you just set the execution variable CONFLICT_CHECK_CODE to 0.
See [the HTTP/1.1 specification](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10) for when you are allowed to use the 409 response, and what to write in the response entity. If this is not appropriate then a 500 Internal server error would be more appropriate (and set CONFLICT_CHECK_CODE to 500 - the framework only tests for non-zero).
### conflict_check_code
This is implemented to check CONFLICT_CHECK_CODE from the previous routine. If you choose to use a different mechanism, then you need to redefine this.
### check_request
This is called for PUT and POST requests. You need to check that the request entity (available in the execution variable REQUEST_ENTITY) is valid for the semantics of the request URI. You should set the execution variable REQUEST_CHECK_CODE to 0 if it is OK. If not, set it to 400 and write the full response, including a status code of 400 Bad Request.
### request_check_code
This routine just checks REQUEST_CHECK_CODE. if you choose to use a different mechanism, then redefine it.
### update_resource
This routine is called for a normal (updating) PUT request. You have to update the state of the resource using the entity saved in the execution environment variable REQUEST_ENTITY (or more likely elsewhere - see what ORDER_HANDLER does). Then write the entire response including a status code of 204 No Content or 500 Internal server error.
## Implementing the policies
* [WSF_OPTIONS_POLICY](WSF_OPTIONS_POLICY.md)
* [WSF_PREVIOUS_POLICY](Wsf-previous-policy.md)
* [WSF_CACHING_POLICY](Wsf-caching-policy.md)

View File

@@ -0,0 +1,52 @@
# Implementing WSF_CACHING_POLICY
This class contains a large number of routines, some of which have sensible defaults.
## age
This is used to generate a **Cache-Control: max-age** header. It says how old the response can before a cache will consider it stale (and therefore will need to revalidate with the server). Common values are zero (always consider it stale) and Never_expires (never always mean up to one year) and 1440 (one day).
## shared_age
This defaults to the same as age, so you only have to redefine it if you want a different value. If different from age, then we generate a **Cache-Control: s-max-age** header. This applies to shared caches only. Otherwise it has the same meaning as age. This overrides the value specified in age for shared caches.
## http_1_0_age
This generates an **Expires** header, and has the same meaning as age, but is understood by HTTP/1.0 caches. By default it has the same value as age. You only need to redefine this if you want to treat HTTP/1.0 caches differently (you might not trust them so well, so you might want to return 0 here).
## is_freely_cacheable
This routine says whether a shared cache can use this response for all client. If True, then it generates a **Cache-Control: public** header. If your data is at all sensitive, then you want to return False here.
## is_transformable
Non-transparent proxies are allowed to make some modifications to headers. If your application relies on this _not_ happening, then you want to return False here. This is the default, so you don't have to do anything. This means a **Cache-Control: no-transform** header will be generated.
But most applications can return True.
## must_revalidate
Some clients request that their private cache ignores server expiry times (and so freely reuse stale responses). If you want to force revalidation anyway in such circumstances, then redefine to return True. In which case, we generate a **Cache-Control: must-revalidate** header.
## must_proxy_revalidate
This is the same as must_revalidate, but only applies to shared caches that are configured to serve stale responses. If you redefine to return True, then we generate a **Cache-Control: proxy-revalidate** header.
## private_headers
This is used to indicate that parts (or all) of a response are considered private to a single user, and should not be freely served from a shared cache. You must implement this routine. Your choices are:
1. Return Void. None of the response is considered private.
1. Return and empty list. All of the response is considered private.
1. Return a list of header names.
If you don't return Void, then a **Cache-Control: private** header will be generated.
## non_cacheable_headers
This is similar to private_headers, and you have the same three choices. the difference is that it is a list of headers (or the whole response) that will not be sent from a cache without revalidation.
If you don't return Void, then a **Cache-Control: no-cache** header will be generated.
## is_sensitive
Is the response to be considered of a sensitive nature? If so, then it will not be archived from a cache. We generate a **Cache-Control: no-store** header.

View File

@@ -0,0 +1,19 @@
# WSF_PREVIOUS_POLICY
This class deals with resources that have moved or gone. The default assumes no such resources. It exists as a separate class, rather than have the routines directly in WSF_SKELETON_HANDLER, as sub-classing it may be convenient for an organisation.
## resource_previously_existed
Redefining this routine is always necessary if you want to deal with any previous resources.
## resource_moved_permanently
Redefine this routine for any resources that have permanently changed location. The framework will generate a 301 Moved Permanently response, and the user agent will automatically redirect the request to (one of) the new location(s) you provide. The user agent will use the new URI for future requests.
## resource_moved_temporarily
This is for resource that have only been moved for a short period. The framework will generate a 302 Found response. The only substantial difference between this and resource_moved_permanently, is that the agent will use the old URI for future requests.
## previous_location
When you redefine resource_moved_permanently or resource_moved_temporarily, the framework will generate a Location header for the new URI, and a hypertext document to the new URI(s). You **must** redefine this routine to provide those locations (the first one you provide will be in the location header).

View File

@@ -0,0 +1,4 @@
# Previous and future meetings
* [Web-meeting: 2012-09-18](meetings/Web-meeting-2012-09-18.md)
* For previous meetings, check the ["meeting" topics](https://groups.google.com/forum/?fromgroups=#!tags/eiffel-web-framework/meeting) on the [forum](http://groups.google.com/group/eiffel-web-framework)

View File

@@ -1,5 +1,5 @@
Use this to suggest new projects, or request features.
The content of this page will be moved to the main [[Projects]] page for time to time.
The content of this page will be moved to the main [Projects](Projects.md) page for time to time.
For any entry, please use this template
----
@@ -12,3 +12,9 @@ For any entry, please use this template
----
## Add support for Swagger
* _Suggested by **Olivier**_
* _Description_: Build a Swagger Eiffel implementation
* _References_: [http://swagger.wordnik.com/](http://swagger.wordnik.com/)
----

View File

@@ -6,13 +6,13 @@ If you are a student, don't hesitate to pick one, or even suggest a new project,
## Evaluate EWF according to the following constraints ...
* _Suggested by **Javier**_
* _Description_: According to http://www.amundsen.com/blog/archives/1130 , evaluate the current design of EWF to see if this match the different points. An other option would be to take the following REST implementation toolkit as a guide to evaluate EWF http://code.google.com/p/implementing-rest/wiki/RESTImplementationToolkit.
* _Description_: According to [http://www.amundsen.com/blog/archives/1130](http://www.amundsen.com/blog/archives/1130) , evaluate the current design of EWF to see if this match the different points. An other option would be to take the following REST implementation toolkit as a guide to evaluate EWF [http://code.google.com/p/implementing-rest/wiki/RESTImplementationToolkit](http://code.google.com/p/implementing-rest/wiki/RESTImplementationToolkit).
## Road to Hypermedia API
* _Suggested by **Javier**_
* _Supervisor_:
* _Suitability_:
* _Description_: describe differents types of Web API, and how you can build them using EWF. Describing Pros and Cons. This should be on http://martinfowler.com/articles/richardsonMaturityModel.html
* _Description_: describe differents types of Web API, and how you can build them using EWF. Describing Pros and Cons. This should be on [http://martinfowler.com/articles/richardsonMaturityModel.html](http://martinfowler.com/articles/richardsonMaturityModel.html)
## Build a video to demonstrate how an Hypermedia API works, and how to build it using EWF
* _Suggested by **Javier**_
@@ -55,8 +55,8 @@ If you are a student, don't hesitate to pick one, or even suggest a new project,
* _Supervisor_:
* _Suitability_: TODO
* _Description_: EWF is relying on the notion of "connector" to achieve portability on various platform and underlying httpd server, currently EWF support any CGI or libFCGI system (i.e apache, IIS, ...), and provide a standalone version thanks to Eiffel Web Nino. The goal now, would be to support specific connector for:
** LightHTTP (http://www.lighttpd.net/)
** nginx (http://nginx.org/en/)
** LightHTTP ([http://www.lighttpd.net/](http://www.lighttpd.net/))
** nginx ([http://nginx.org/en/](http://nginx.org/en/))
## Concurrenty and EWF
* _Suggested by **Jocelyn**_
@@ -75,7 +75,7 @@ If you are a student, don't hesitate to pick one, or even suggest a new project,
* _Supervisor_:
* _Suitability_: TODO
* _Description_: Provide an implementation of websocket with EWF and eventually Eiffel Web Nino, then demonstrate it on a simple example. WebSocket is a web technology providing for bi-directional, full-duplex communications channels over a single TCP connection.
* See http://en.wikipedia.org/wiki/Websocket
* See [http://en.wikipedia.org/wiki/Websocket](http://en.wikipedia.org/wiki/Websocket)
----
# Usage of EWF
@@ -84,18 +84,19 @@ If you are a student, don't hesitate to pick one, or even suggest a new project,
* _Suggested by **Javier**_
* _Supervisor_:
* _Suitability_: TODO
* _Description_: Build a HAL browser to discover an API using HAL mediatype. The browser will be able to follow the links, and display the transmitted data. This could be a vision2 application inspired by http://haltalk.herokuapp.com/explorer/hal_browser.html#/. HAL stands for Hypertext Application Language see http://stateless.co/hal_specification.html.
* _Description_: Build a HAL browser to discover an API using HAL mediatype. The browser will be able to follow the links, and display the transmitted data. This could be a vision2 application inspired by [http://haltalk.herokuapp.com/explorer/hal_browser.html#/](http://haltalk.herokuapp.com/explorer/hal_browser.html#/). HAL stands for Hypertext Application Language see [http://stateless.co/hal_specification.html](http://stateless.co/hal_specification.html).
## Collection-JSON browser
* _Suggested by **Javier**_
* _Supervisor_:
* _Suitability_: TODO
* _Description_: Build a Collection/JSON browser to discover an API using Collection/JSON mediatype. The browser will be able to follow the links, and display the transmitted data. This could be a vision2 application inspired by http://haltalk.herokuapp.com/explorer/hal_browser.html#/. Collection+JSON is a JSON-based read/write hypermedia-type, see http://www.amundsen.com/media-types/collection/
* _Description_: Build a Collection/JSON browser to discover an API using Collection/JSON mediatype. The browser will be able to follow the links, and display the transmitted data. This could be a vision2 application inspired by [http://haltalk.herokuapp.com/explorer/hal_browser.html#/](http://haltalk.herokuapp.com/explorer/hal_browser.html#/). Collection+JSON is a JSON-based read/write hypermedia-type, see [http://www.amundsen.com/media-types/collection/](http://www.amundsen.com/media-types/collection/)
## Build a simple CMS with EWF
* _Suggested by **Jocelyn**_
* _Supervisor_:
* _Suitability_: TODO
* _Status_: started, and open for contribution, collaboration, please contact Jocelyn.
* _Description_: Using EWF, Build a simple CMS (Content Management System) framework and then an example. It should provide common features such as:
- user management (register, login, lost password -> send email)
- page editing
@@ -118,7 +119,7 @@ If you are a student, don't hesitate to pick one, or even suggest a new project,
* _Suggested by **Javier**_
* _Supervisor_:
* _Suitability_: TODO
* _Description_: Use XHTML as a media type to for hypermedia API. See http://codeartisan.blogspot.com.ar/2012/07/using-html-as-media-type-for-your-api.html
* _Description_: Use XHTML as a media type to for hypermedia API. See [http://codeartisan.blogspot.com.ar/2012/07/using-html-as-media-type-for-your-api.html](http://codeartisan.blogspot.com.ar/2012/07/using-html-as-media-type-for-your-api.html)
## Add support for Mediatype such as RSS, ATOM, ...
* _Suggested by **Jocelyn**_
@@ -154,24 +155,24 @@ If you are a student, don't hesitate to pick one, or even suggest a new project,
* _Suitability_: TODO
* _Description_: Design and build a Single Sign On implementation for Eiffel. That should include the authentication server, and at least one Eiffel client component (it would be convenient to also provide php, js, ...). In the same spirit, having Eiffel client for popular SSO server would be appreciated as well.
* _Reference_:
- http://en.wikipedia.org/wiki/Single_sign-on
- http://en.wikipedia.org/wiki/List_of_single_sign-on_implementations
- [http://en.wikipedia.org/wiki/Single_sign-on](http://en.wikipedia.org/wiki/Single_sign-on)
- [http://en.wikipedia.org/wiki/List_of_single_sign-on_implementations](http://en.wikipedia.org/wiki/List_of_single_sign-on_implementations)
## library: Template engine
* _Suggested by **Jocelyn**_
* _Supervisor_:
* _Suitability_: TODO
* _Description_: Get inspired by any existing template engine, and build one for Eiffel, this should be easily usable within a web application. This could be inspired, or implementation of standard template engine, this way people can reuse existing content, or migrate easily their application to EWF. For inspiration, one can look at:
- http://www.smarty.net/
- http://mustache.github.com/
- http://en.wikipedia.org/wiki/Template_engine_(web) ... they are plenty of them, a comparison of the different engine would help.
- [http://www.smarty.net/](http://www.smarty.net/)
- [http://mustache.github.com/](http://mustache.github.com/)
- [http://en.wikipedia.org/wiki/Web_template_system](http://en.wikipedia.org/wiki/Web_template_system) ... they are plenty of them, a comparison of the different engine would help.
* This is not specific to EWF, but it will be very useful in website context.
## library: Wikitext, markdown parser and render engine
* _Suggested by **Jocelyn**_
* _Supervisor_:
* _Suitability_: TODO
* _Description_: Build component to support (read and write, and why not convert), lightweight markup language (see http://en.wikipedia.org/wiki/Lightweight_markup_language) such as wikitext, markdown, and other. The component should be able to read/scan, but also produce an HTML output. Focus first on wikitext, and markdown since they seems to be the most popular.
* _Description_: Build component to support (read and write, and why not convert), lightweight markup language (see [http://en.wikipedia.org/wiki/Lightweight_markup_language](http://en.wikipedia.org/wiki/Lightweight_markup_language)) such as wikitext, markdown, and other. The component should be able to read/scan, but also produce an HTML output. Focus first on wikitext, and markdown since they seems to be the most popular.
* Then , a nice addition would be to render those lightweight markup lang into Vision2 widget (not related to EWF, but could be useful to build (editor) desktop application)
## library: Web component to build HTML5 widget
@@ -194,16 +195,16 @@ If you are a student, don't hesitate to pick one, or even suggest a new project,
* _Suitability_: TODO
* _Description_: TODO
* Generic client that can be customized (see design in slide 12)
* http://s3.amazonaws.com/cimlabs/Oredev-Hypermedia-APIs.pdf
* video http://vimeo.com/20781278
* [http://s3.amazonaws.com/cimlabs/Oredev-Hypermedia-APIs.pdf](http://s3.amazonaws.com/cimlabs/Oredev-Hypermedia-APIs.pdf)
* video [http://vimeo.com/20781278](http://vimeo.com/20781278)
## Create a Client Cache based on Apache commons Client Cache.
* _Suggested by **Javier**_
* _Supervisor_:
* _Suitability_: TODO
* _Description_: TODO
* http://hc.apache.org/httpcomponents-client-ga/httpclient-cache/index.html
* http://labs.xfinity.com/benchmarking-the-httpclient-caching-module
* [http://hc.apache.org/httpcomponents-client-ga/httpclient-cache/index.html](http://hc.apache.org/httpcomponents-client-ga/httpclient-cache/index.html)
* [http://labs.xfinity.com/benchmarking-the-httpclient-caching-module](http://labs.xfinity.com/benchmarking-the-httpclient-caching-module)
## Add SSL support to Eiffel Net
* _Suggested by **Jocelyn**_
@@ -225,7 +226,14 @@ If you are a student, don't hesitate to pick one, or even suggest a new project,
* This should reuse and improve the "http_client" provided by EWF. Eventually also write the EiffelNet implementation to be independant from cURL
* **Requirement**: OAuth client eiffel component
## Build a ESI preprocessor, or proxy
* _Suggested by **Jocelyn**_
* _Supervisor_:
* _Suitability_: TODO
* _Description_: TODO
* See: [http://en.wikipedia.org/wiki/Edge_Side_Includes](http://en.wikipedia.org/wiki/Edge_Side_Includes)
----
# Feel free to add new idea below this line
----
Use the following page [[Projects new suggestions]] to suggest new project, or request a feature.
Use the following page [Projects new suggestions](Projects-new-suggestions.md) to suggest new project, or request a feature.

Some files were not shown because too many files have changed in this diff Show More