first commit

This commit is contained in:
2025-07-07 16:01:27 -03:00
commit 6d24d7d269
148 changed files with 33981 additions and 0 deletions

20
.abapgit.xml Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DATA>
<MASTER_LANGUAGE>E</MASTER_LANGUAGE>
<STARTING_FOLDER>/src/</STARTING_FOLDER>
<FOLDER_LOGIC>FULL</FOLDER_LOGIC>
<IGNORE>
<item>/.gitignore</item>
<item>/LICENSE</item>
<item>/README.md</item>
<item>/package.json</item>
<item>/.travis.yml</item>
<item>/.gitlab-ci.yml</item>
<item>/abaplint.json</item>
<item>/azure-pipelines.yml</item>
</IGNORE>
</DATA>
</asx:values>
</asx:abap>

0
README.md Normal file
View File

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_ENQU" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DD25V>
<VIEWNAME>EZDEMO_ABAP_LOCK</VIEWNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<AGGTYPE>E</AGGTYPE>
<ROOTTAB>ZDEMO_ABAP_RAPT1</ROOTTAB>
<DDTEXT>Lock on demo table</DDTEXT>
<ABAP_LANGUAGE_VERSION>5</ABAP_LANGUAGE_VERSION>
</DD25V>
<DD26E_TABLE>
<DD26E>
<VIEWNAME>EZDEMO_ABAP_LOCK</VIEWNAME>
<TABNAME>ZDEMO_ABAP_RAPT1</TABNAME>
<TABPOS>0001</TABPOS>
<FORTABNAME>ZDEMO_ABAP_RAPT1</FORTABNAME>
<ENQMODE>E</ENQMODE>
</DD26E>
</DD26E_TABLE>
<DD27P_TABLE>
<DD27P>
<VIEWNAME>EZDEMO_ABAP_LOCK</VIEWNAME>
<OBJPOS>0001</OBJPOS>
<VIEWFIELD>CLIENT</VIEWFIELD>
<TABNAME>ZDEMO_ABAP_RAPT1</TABNAME>
<FIELDNAME>CLIENT</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ENQMODE>E</ENQMODE>
</DD27P>
<DD27P>
<VIEWNAME>EZDEMO_ABAP_LOCK</VIEWNAME>
<OBJPOS>0002</OBJPOS>
<VIEWFIELD>KEY_FIELD</VIEWFIELD>
<TABNAME>ZDEMO_ABAP_RAPT1</TABNAME>
<FIELDNAME>KEY_FIELD</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ENQMODE>E</ENQMODE>
</DD27P>
</DD27P_TABLE>
</asx:values>
</asx:abap>
</abapGit>

10
src/package.devc.xml Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DEVC" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DEVC>
<CTEXT>ABAP Cheat Sheets</CTEXT>
</DEVC>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,20 @@
***********************************************************************
*
* RAP BO provider (i. e. ABAP behavior pool/ABP)
* for a RAP demo scenario
*
* See more information in the CCIMP include (local types tab in ADT).
*
**********************************************************************
"! <p class="shorttext synchronized">Behavior implementation for RAP demo scenario (draft BO)</p>
"! The class represents a RAP BO provider (i. e. an ABAP behavior pool/ABP) for a RAP demo scenario
"! (managed, draft-enabled RAP BO with late numbering).
CLASS zbp_demo_abap_rap_draft_m DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zdemo_abap_rap_draft_m.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ZBP_DEMO_ABAP_RAP_DRAFT_M IMPLEMENTATION.
ENDCLASS.

View File

@@ -0,0 +1,240 @@
***********************************************************************
*
* RAP BO provider (i. e. ABAP behavior pool/ABP)
* for a RAP demo scenario
*
* - RAP scenario: "RAP calculator" (managed, draft-enabled RAP BO with
* late numbering)
* - Data model: Consists of a root entity alone.
* The BDEF defines the behavior for this entity. The definitions in the
* BDEF determine which methods must be implemented in the ABAP behavior
* pool (ABP). Note that the view contains many annotations for the
* SAP Fiori UI.
*
* ----------------------------- NOTE -----------------------------------
* This simplified example is not a real life scenario and rather
* focuses on the technical side by giving an idea how the communication
* and data exchange between a RAP BO consumer, which is a class
* in this case, and RAP BO provider can work. Additionally, it shows
* how the methods for non-standard RAP BO operations might be
* self-implemented in an ABP. The example is intentionally kept
* short and simple and focuses on specific RAP aspects. For this reason,
* the example might not fully meet the requirements of the RAP BO contract.
*
* You can also use side effects to trigger data
* changes (in terms of this example, the recalculation of the calculation
* result) and other things based on data changes in UI scenarios with
* draft-enabled BOs.
*
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
CLASS lhc_calc DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS delete_all FOR MODIFY
IMPORTING keys FOR ACTION calc~delete_all.
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR calc RESULT result.
METHODS validate FOR VALIDATE ON SAVE
IMPORTING keys FOR calc~validate.
METHODS det_modify FOR DETERMINE ON MODIFY
IMPORTING keys FOR calc~det_modify.
METHODS calculation FOR MODIFY
IMPORTING keys FOR ACTION calc~calculation.
ENDCLASS.
CLASS lhc_calc IMPLEMENTATION.
METHOD delete_all.
"Purpose: The method deletes all persisted database entries.
DATA all_keys TYPE TABLE FOR DELETE zdemo_abap_rap_draft_m.
SELECT id FROM zdemo_abap_tabca INTO CORRESPONDING FIELDS OF TABLE @all_keys.
READ ENTITIES OF zdemo_abap_rap_draft_m IN LOCAL MODE
ENTITY calc
ALL FIELDS WITH CORRESPONDING #( all_keys )
RESULT DATA(lt_del).
IF lt_del IS NOT INITIAL.
MODIFY ENTITY IN LOCAL MODE zdemo_abap_rap_draft_m
DELETE FROM CORRESPONDING #( lt_del ).
APPEND VALUE #( %msg = new_message_with_text( text = 'All persisted calculations were deleted.'
severity = if_abap_behv_message=>severity-information )
) TO reported-calc.
ELSE.
APPEND VALUE #( %msg = new_message_with_text( text = 'No persisted calculations available.'
severity = if_abap_behv_message=>severity-information )
) TO reported-calc.
ENDIF.
ENDMETHOD.
METHOD get_global_authorizations.
"Purposely kept without implementation.
ENDMETHOD.
METHOD validate.
"Retrieving instances based on requested keys
READ ENTITIES OF zdemo_abap_rap_draft_m IN LOCAL MODE
ENTITY calc
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(result_validate)
FAILED DATA(f).
CHECK result_validate IS NOT INITIAL.
"Various calculation errors are handled.
LOOP AT result_validate ASSIGNING FIELD-SYMBOL(<fs>).
APPEND VALUE #( %tky = <fs>-%tky
%state_area = 'VALIDATE_CALCULATION'
) TO reported-calc.
IF <fs>-calc_result = `Wrong operator`.
APPEND VALUE #( %tky = <fs>-%tky ) TO failed-calc.
APPEND VALUE #( %tky = <fs>-%tky
%state_area = 'VALIDATE_CALCULATION'
%msg = new_message_with_text( text = 'Only + - * / P allowed as operators.'
severity = if_abap_behv_message=>severity-error )
"%element highlights the input field
%element-arithm_op = if_abap_behv=>mk-on
) TO reported-calc.
ELSEIF <fs>-calc_result = `Division by 0`.
APPEND VALUE #( %tky = <fs>-%tky ) TO failed-calc.
APPEND VALUE #( %tky = <fs>-%tky
%state_area = 'VALIDATE_CALCULATION'
%msg = new_message_with_text( text = 'Zero division not possible.'
severity = if_abap_behv_message=>severity-error )
%element-arithm_op = if_abap_behv=>mk-on
%element-num2 = if_abap_behv=>mk-on
) TO reported-calc.
ELSEIF <fs>-calc_result = `Overflow error`.
APPEND VALUE #( %tky = <fs>-%tky ) TO failed-calc.
APPEND VALUE #( %tky = <fs>-%tky
%state_area = 'VALIDATE_CALCULATION'
%msg = new_message_with_text( text = 'Check the numbers. Try smaller ones.'
severity = if_abap_behv_message=>severity-error )
%element-num1 = if_abap_behv=>mk-on
%element-num2 = if_abap_behv=>mk-on
) TO reported-calc.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD det_modify.
MODIFY ENTITIES OF zdemo_abap_rap_draft_m IN LOCAL MODE
ENTITY calc
EXECUTE calculation
FROM CORRESPONDING #( keys ).
ENDMETHOD.
METHOD calculation.
READ ENTITIES OF zdemo_abap_rap_draft_m IN LOCAL MODE
ENTITY calc
FIELDS ( num1 num2 arithm_op ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_calc)
FAILED DATA(f).
LOOP AT lt_calc ASSIGNING FIELD-SYMBOL(<calc>).
TRY.
<calc>-calc_result = SWITCH #( <calc>-arithm_op
WHEN `+` THEN <calc>-num1 + <calc>-num2
WHEN `-` THEN <calc>-num1 - <calc>-num2
WHEN `*` THEN <calc>-num1 * <calc>-num2
WHEN `/` THEN <calc>-num1 / <calc>-num2
WHEN `P` THEN ipow( base = <calc>-num1 exp = <calc>-num2 )
ELSE `Wrong operator` ).
"Bringing "-" to the front in case of negative values in the string
IF <calc>-calc_result CA `-`.
<calc>-calc_result = shift_right( val = <calc>-calc_result circular = 1 ).
ENDIF.
"Removing trailing .0 from the string
REPLACE PCRE `\.0+\b` IN <calc>-calc_result WITH ``.
"Handling the fact that ABAP allows division by zero if the dividend itself is zero.
IF <calc>-num1 = 0 AND <calc>-num2 = 0 AND <calc>-arithm_op = `/`.
<calc>-calc_result = `Division by 0`.
ENDIF.
CATCH cx_sy_zerodivide.
<calc>-calc_result = `Division by 0`.
CATCH cx_sy_arithmetic_overflow.
<calc>-calc_result = `Overflow error`.
ENDTRY.
ENDLOOP.
MODIFY ENTITY IN LOCAL MODE zdemo_abap_rap_draft_m
UPDATE FIELDS ( calc_result )
WITH CORRESPONDING #( lt_calc ).
ENDMETHOD.
ENDCLASS.
CLASS lsc_zdemo_abap_rap_draft_m DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS adjust_numbers REDEFINITION.
ENDCLASS.
CLASS lsc_zdemo_abap_rap_draft_m IMPLEMENTATION.
METHOD adjust_numbers.
"The newly created entity instances are given their final key
"only shortly before saving in the database in the adjust_numbers method.
"Until then, the business logic uses a temporary key that has to be replaced.
"In this very simplified example, the key 'id' is purposely typed with the
"type sysuuid_x16 which can accept the value used in %pid to finally ensure
"that there is a unique key and the instance can be stored in the database.
"Hence, the final key 'id' is in this example just the value used for %pid.
LOOP AT mapped-calc ASSIGNING FIELD-SYMBOL(<fs>).
<fs>-%key-id = <fs>-%pid.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZBP_DEMO_ABAP_RAP_DRAFT_M</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>Behavior implementation for RAP demo scenario (draft BO)</DESCRIPT>
<CATEGORY>06</CATEGORY>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<CLSDEFINT>ZDEMO_ABAP_RAP_DRAFT_M</CLSDEFINT>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,20 @@
***********************************************************************
*
* RAP BO provider (i. e. ABAP behavior pool/ABP)
* for a RAP demo scenario
*
* See more information in the CCIMP include (local types tab in ADT).
*
**********************************************************************
"! <p class="shorttext synchronized">Behavior implementation for RAP demo scenario (managed BO)</p>
"! The class represents a RAP BO provider (i. e. an ABAP behavior pool/ABP) for a RAP demo scenario
"! (managed RAP BO with external numbering).
CLASS zbp_demo_abap_rap_ro_m DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zdemo_abap_rap_ro_m.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ZBP_DEMO_ABAP_RAP_RO_M IMPLEMENTATION.
ENDCLASS.

View File

@@ -0,0 +1,124 @@
***********************************************************************
*
* RAP BO provider (i. e. ABAP behavior pool/ABP)
* for a RAP demo scenario
*
* - RAP scenario: managed RAP BO, external numbering
* - Data model: Consists of a root entity and one child entity. The BDEF
* defines the behavior for these two entities which are connected via
* a CDS composition relation. The definitions in the BDEF determine
* which methods must be implemented in this ABAP behavior pool (ABP).
*
* ----------------------------- NOTE -----------------------------------
* This simplified example is not a real life scenario and rather
* focuses on the technical side by giving an idea how the communication
* and data exchange between a RAP BO consumer, which is a class
* in this case, and RAP BO provider can work. Additionally, it shows
* how the methods for non-standard RAP BO operations might be
* self-implemented in an ABP. The example is is intentionally kept
* short and simple and focuses on specific RAP aspects. For this reason,
* the example might not fully meet the requirements of the RAP BO contract.
*
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
CLASS lhc_root DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR root RESULT result.
METHODS multiply_by_2 FOR MODIFY
IMPORTING keys FOR ACTION root~multiply_by_2.
METHODS det_add_text FOR DETERMINE ON SAVE
IMPORTING keys FOR root~det_add_text.
METHODS val FOR VALIDATE ON SAVE
IMPORTING keys FOR root~val.
ENDCLASS.
CLASS lhc_root IMPLEMENTATION.
METHOD get_global_authorizations.
ENDMETHOD.
METHOD multiply_by_2.
"Retrieving instances based on requested keys
READ ENTITIES OF zdemo_abap_rap_ro_m IN LOCAL MODE
ENTITY root
FIELDS ( field3 field4 ) WITH CORRESPONDING #( keys )
RESULT DATA(result)
FAILED failed.
"If read result is initial, stop further method execution.
CHECK result IS NOT INITIAL.
"Multiply integer values by 2
MODIFY ENTITIES OF zdemo_abap_rap_ro_m IN LOCAL MODE
ENTITY root
UPDATE FIELDS ( field3 field4 ) WITH VALUE #( FOR key IN result ( %tky = key-%tky
field3 = key-field3 * 2
field4 = key-field4 * 2 ) ).
ENDMETHOD.
METHOD det_add_text.
READ ENTITIES OF zdemo_abap_rap_ro_m IN LOCAL MODE
ENTITY root
FIELDS ( field2 ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_res).
"If read result is initial, stop further method execution.
CHECK lt_res IS NOT INITIAL.
"field2 is changed
MODIFY ENTITIES OF zdemo_abap_rap_ro_m IN LOCAL MODE
ENTITY root
UPDATE FIELDS ( field2 )
WITH VALUE #( FOR key IN lt_res ( %tky = key-%tky
field2 = |{ key-field2 }_#| ) ).
ENDMETHOD.
METHOD val.
READ ENTITIES OF zdemo_abap_rap_ro_m IN LOCAL MODE
ENTITY root
FIELDS ( field3 ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_res).
"If read result is initial, stop further method execution.
CHECK lt_res IS NOT INITIAL.
LOOP AT lt_res ASSIGNING FIELD-SYMBOL(<fs_res>).
IF <fs_res>-field3 > 1000.
APPEND VALUE #( %tky = <fs_res>-%tky
%fail-cause = if_abap_behv=>cause-disabled
)
TO failed-root.
APPEND VALUE #( %tky = <fs_res>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Validation failed!' )
) TO reported-root.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZBP_DEMO_ABAP_RAP_RO_M</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>Behavior implementation for RAP demo scenario (managed BO)</DESCRIPT>
<CATEGORY>06</CATEGORY>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<CLSDEFINT>ZDEMO_ABAP_RAP_RO_M</CLSDEFINT>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,7 @@
CLASS zbp_demo_abap_rap_ro_m_as DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zdemo_abap_rap_ro_m_as.
PUBLIC SECTION.
CLASS-DATA num_raised_events TYPE i.
ENDCLASS.
CLASS zbp_demo_abap_rap_ro_m_as IMPLEMENTATION.
ENDCLASS.

View File

@@ -0,0 +1,109 @@
CLASS lhc_zdemo_abap_rap_ro_m_as DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR root RESULT result.
METHODS calc FOR MODIFY
IMPORTING keys FOR ACTION root~calc.
METHODS det_modify FOR DETERMINE ON MODIFY
IMPORTING keys FOR root~det_modify.
ENDCLASS.
CLASS lhc_zdemo_abap_rap_ro_m_as IMPLEMENTATION.
METHOD get_global_authorizations.
ENDMETHOD.
METHOD calc.
READ ENTITY IN LOCAL MODE zdemo_abap_rap_ro_m_as
FIELDS ( num1 num2 arithm_op crea_date_time lchg_date_time ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_calc)
FAILED DATA(f).
DATA(timestamp) = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) ).
LOOP AT lt_calc ASSIGNING FIELD-SYMBOL(<calc>).
TRY.
<calc>-calc_result = SWITCH #( <calc>-arithm_op
WHEN `+` THEN |{ CONV decfloat34( <calc>-num1 + <calc>-num2 ) STYLE = SIMPLE }|
WHEN `-` THEN |{ CONV decfloat34( <calc>-num1 - <calc>-num2 ) STYLE = SIMPLE }|
WHEN `*` THEN |{ CONV decfloat34( <calc>-num1 * <calc>-num2 ) STYLE = SIMPLE }|
WHEN `/` THEN |{ CONV decfloat34( <calc>-num1 / <calc>-num2 ) STYLE = SIMPLE }|
WHEN `P` THEN |{ CONV decfloat34( ipow( base = <calc>-num1 exp = <calc>-num2 ) ) STYLE = SIMPLE }|
ELSE `Wrong operator` ).
"Handling the fact that ABAP allows division by zero if the dividend itself is zero.
IF <calc>-num1 = 0 AND <calc>-num2 = 0 AND <calc>-arithm_op = `/`.
<calc>-calc_result = `Division by 0`.
ENDIF.
CATCH cx_sy_zerodivide.
<calc>-calc_result = `Division by 0`.
CATCH cx_sy_arithmetic_overflow.
<calc>-calc_result = `Overflow error`.
ENDTRY.
ENDLOOP.
MODIFY ENTITY IN LOCAL MODE zdemo_abap_rap_ro_m_as
UPDATE FIELDS ( calc_result )
WITH CORRESPONDING #( lt_calc ).
ENDMETHOD.
METHOD det_modify.
MODIFY ENTITY IN LOCAL MODE zdemo_abap_rap_ro_m_as
EXECUTE calc
FROM CORRESPONDING #( keys ).
ENDMETHOD.
ENDCLASS.
CLASS lsc_zdemo_abap_rap_ro_m_as DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS save_modified REDEFINITION.
METHODS cleanup_finalize REDEFINITION.
ENDCLASS.
CLASS lsc_zdemo_abap_rap_ro_m_as IMPLEMENTATION.
METHOD save_modified.
IF create-root IS NOT INITIAL.
RAISE ENTITY EVENT zdemo_abap_rap_ro_m_as~created
FROM VALUE #( FOR <cr> IN create-root (
%key = VALUE #( id = <cr>-id ) ) ).
zbp_demo_abap_rap_ro_m_as=>num_raised_events = zbp_demo_abap_rap_ro_m_as=>num_raised_events + lines( create-root ).
ENDIF.
IF update-root IS NOT INITIAL.
"Demonstrating the BDEF derived type TYPE TABLE FOR EVENT
DATA evt_tab_up TYPE TABLE FOR EVENT zdemo_abap_rap_ro_m_as~updated.
evt_tab_up = VALUE #( FOR <up> IN update-root INDEX INTO updidx (
%key = VALUE #( id = <up>-id )
%param = VALUE #( col1 = 'Event raised'
col2 = |UPDATED ({ updidx })| ) ) ).
RAISE ENTITY EVENT zdemo_abap_rap_ro_m_as~updated FROM evt_tab_up.
zbp_demo_abap_rap_ro_m_as=>num_raised_events = zbp_demo_abap_rap_ro_m_as=>num_raised_events + lines( update-root ).
ENDIF.
IF delete-root IS NOT INITIAL.
RAISE ENTITY EVENT zdemo_abap_rap_ro_m_as~deleted
FROM VALUE #( FOR <del> IN delete-root INDEX INTO delidx (
%key = VALUE #( id = <del>-id )
%param = VALUE #( col1 = 'Event raised'
col2 = |DELETED ({ delidx })| ) ) ).
zbp_demo_abap_rap_ro_m_as=>num_raised_events = zbp_demo_abap_rap_ro_m_as=>num_raised_events + lines( delete-root ).
ENDIF.
ENDMETHOD.
METHOD cleanup_finalize.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZBP_DEMO_ABAP_RAP_RO_M_AS</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>Behavior Implementation for ZDEMO_ABAP_RAP_RO_M_AS</DESCRIPT>
<CATEGORY>06</CATEGORY>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<CLSDEFINT>ZDEMO_ABAP_RAP_RO_M_AS</CLSDEFINT>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,20 @@
***********************************************************************
*
* RAP BO provider (i. e. ABAP behavior pool/ABP)
* for a RAP demo scenario
*
* See more information in the CCIMP include (local types tab in ADT).
*
**********************************************************************
"! <p class="shorttext synchronized">Behavior implementation for RAP demo scenario (unmanaged BO)</p>
"! The class represents a RAP BO provider (i. e. an ABAP behavior pool/ABP) for a RAP demo scenario
"! (unmanaged RAP BO with external numbering).
CLASS zbp_demo_abap_rap_ro_u DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zdemo_abap_rap_ro_u.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ZBP_DEMO_ABAP_RAP_RO_U IMPLEMENTATION.
ENDCLASS.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZBP_DEMO_ABAP_RAP_RO_U</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>Behavior implementation for RAP demo scenario (unmanaged BO)</DESCRIPT>
<CATEGORY>06</CATEGORY>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<CLSDEFINT>ZDEMO_ABAP_RAP_RO_U</CLSDEFINT>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,371 @@
***********************************************************************
*
* ABAP cheat sheet: AMDP
*
* -------------------------- PURPOSE ----------------------------------
* - Example to demonstrate AMDP procedures and functions. It includes
* a CDS table function.
* - NOTE:
* - The example covers basics regarding AMDP method declarations
* and implementations.
* - The purpose is to give you a rough idea about AMDP. Therefore,
* the SQLScript code used in the method implementations is
* fairly simple. AMDP is not needed in simple cases like these.
* - The example is primarily intended for ABAP Cloud.
* For example, in ABAP Cloud only read-only operations are possible.
* In general, there are more syntax options available in classic
* ABAP. Check the ABAP Keyword Documentation for more details and
* examples.
*
* ----------------------- GETTING STARTED -----------------------------
* - Open the class with the ABAP development tools for Eclipse (ADT).
* - Choose F9 to run the class.
* - Check the console output.
* - To understand the context and the ABAP syntax used, check the notes
* included in the class as comments or refer to the respective topic
* in the ABAP Keyword Documentation.
* - Due to the amount of output in the console, the examples include
* numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example
* sections. Plus, the variable name is displayed in most cases. Hence,
* to easier and faster find the relevant output in the console, just
* search in the console for the number/variable name (CTRL+F in the
* console) or use the debugger.
*
* ----------------------------- NOTE -----------------------------------
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: AMDP</p>
"! Example to demonstrate AMDP procedures and functions.<br>Choose F9 in ADT to run the class.
CLASS zcl_demo_abap_amdp DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES:
if_oo_adt_classrun, "Interface for displaying output
if_amdp_marker_hdb. "This interface specification is mandatory for an AMDP class
"Various internal table type specifications for the parameters of AMDP methods
"Note: Only table and elementary data types are possible for the parameters.
TYPES carr_tab TYPE STANDARD TABLE OF zdemo_abap_carr_ve WITH EMPTY KEY.
TYPES fli_tab TYPE STANDARD TABLE OF zdemo_abap_fli_ve WITH EMPTY KEY.
TYPES:
"Structured data type as basis for the table type below
BEGIN OF carr_fli_struc,
carrname TYPE zdemo_abap_carr_ve-carrname,
connid TYPE zdemo_abap_flsch_ve-connid,
cityfrom TYPE zdemo_abap_flsch_ve-cityfrom,
cityto TYPE zdemo_abap_flsch_ve-cityto,
END OF carr_fli_struc,
"Internal table type
carr_fli_tab TYPE STANDARD TABLE OF carr_fli_struc WITH EMPTY KEY,
"Structured data type as basis for the table type below
BEGIN OF fli_struc,
carrid TYPE zdemo_abap_flsch_ve-carrid,
connid TYPE zdemo_abap_flsch_ve-connid,
cityfrom TYPE zdemo_abap_flsch_ve-cityfrom,
cityto TYPE zdemo_abap_flsch_ve-cityto,
fltime TYPE zdemo_abap_flsch_ve-fltime,
END OF fli_struc,
"Internal table type
flsch_tab TYPE STANDARD TABLE OF zdemo_abap_flsch_ve WITH EMPTY KEY.
"Various instance method declarations
"The selection for instance and static methods is irrelevant for the example.
"It is just meant to visualize that AMDP methods can be declared as either of them.
"AMDP procedure
"It's a simple AMDP procedure having only an output parameter with tabular type.
"Note the parameter declaration that includes the mandatory passing by value.
"This is true for all of the AMDP method declarations.
METHODS select_carriers
AMDP OPTIONS READ-ONLY CDS SESSION CLIENT dependent
EXPORTING VALUE(carr_tab) TYPE carr_tab.
"AMDP procedure to call an AMDP table function
"As can be seen in the implementation part, this example method calls the
"AMDP table function get_carr_fli. AMDP table functions can only be called
"by other AMDP methods.
METHODS select_get_carr_fli
AMDP OPTIONS READ-ONLY CDS SESSION CLIENT dependent
IMPORTING VALUE(carrid) TYPE zdemo_abap_fli_ve-carrid
EXPORTING VALUE(carr_fli_tab) TYPE carr_fli_tab.
"Various static method declarations
"The purpose of the implementation of the static constructor in this example is to
"fill a demo database table to have data to work with in the example.
CLASS-METHODS class_constructor.
"AMDP procedure
"This method demonstrates the calling of an AMDP procedure from SQLScript.
"In this example, the selection of data is 'delegated' to another AMDP method get_flights_amdp
"in the same AMDP class. The method declaration includes the addition RAISING with an
"exception class for AMDP-specific exceptions.
CLASS-METHODS get_flights
AMDP OPTIONS READ-ONLY CDS SESSION CLIENT dependent
IMPORTING VALUE(carrid) TYPE zdemo_abap_fli_ve-carrid
EXPORTING VALUE(fli_tab) TYPE fli_tab
RAISING cx_amdp_execution_error.
"AMDP Table Function for CDS Table Function
"Note that, in this case, a static method declaration is required along with the special
"syntax FOR TABLE FUNCTION. Plus, there are no parameters specified and the declaration
"is made in the PUBLIC visibility section.
CLASS-METHODS flight_analysis FOR TABLE FUNCTION zdemo_abap_table_function.
PROTECTED SECTION.
PRIVATE SECTION.
"AMDP procedure
"This method demonstrates the calling of an AMDP procedure from SQLScript as mentioned above.
CLASS-METHODS get_flights_amdp
AMDP OPTIONS READ-ONLY CDS SESSION CLIENT dependent
IMPORTING VALUE(carrid) TYPE zdemo_abap_fli_ve-carrid
EXPORTING VALUE(fli_tab) TYPE fli_tab
RAISING cx_amdp_execution_error.
"AMDP table function
"AMDP table functions can only be called by other AMDP methods. In this example,
"the AMDP procedure select_get_carr_fli calls this AMDP table function.
METHODS get_carr_fli
AMDP OPTIONS READ-ONLY CDS SESSION CLIENT dependent
IMPORTING VALUE(carrid) TYPE zdemo_abap_flsch_ve-carrid
RETURNING VALUE(carr_fli_tab) TYPE carr_fli_tab.
CONSTANTS nl TYPE string VALUE cl_abap_char_utilities=>newline.
ENDCLASS.
CLASS zcl_demo_abap_amdp IMPLEMENTATION.
METHOD class_constructor.
"Filling demo database tables.
zcl_demo_abap_aux=>fill_dbtabs( ).
ENDMETHOD.
METHOD flight_analysis
BY DATABASE FUNCTION
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zdemo_abap_flsch_ve
zdemo_abap_carr_ve.
* Reading data from two CDS view entities
itab_cities =
select DISTINCT
zdemo_abap_flsch_ve.mandt as client,
zdemo_abap_flsch_ve.carrid as carrier_id,
zdemo_abap_flsch_ve.airpfrom as airport_from,
zdemo_abap_flsch_ve.airpto as airport_to,
zdemo_abap_flsch_ve.fltime as flight_time,
zdemo_abap_flsch_ve.distance as flight_distance,
zdemo_abap_flsch_ve.distid as unit
from zdemo_abap_flsch_ve;
itab_carrier_names =
select distinct
zdemo_abap_carr_ve.mandt as client,
zdemo_abap_carr_ve.carrid as carrier_id,
zdemo_abap_carr_ve.carrname as carrier_name
from zdemo_abap_carr_ve;
* Returning joined data using an inner join
return
select fl.client, fl.carrier_id, ca.carrier_name,
* Departure and destination airports are concatenated; then all results are joined by string aggregation
string_agg( concat(concat(fl.airport_from,' -> '),fl.airport_to), ', ' ORDER BY fl.airport_from) AS connections,
* Retrieving the average flight time of all flights by carrier
AVG( fl.flight_time ) as avg_flight_time,
* Retrieving the average flight distance of all flights by carrier; miles are converted to kilometers
avg( case 'MI'
when fl.unit then fl.flight_distance * 1.609
ELSE fl.flight_distance
END ) AS avg_distance
FROM :itab_cities AS fl
INNER JOIN :itab_carrier_names AS ca
ON ca.client = fl.client
AND ca.carrier_id = fl.carrier_id
WHERE fl.client = ca.client AND fl.carrier_id = ca.carrier_id
GROUP BY fl.client, ca.carrier_name, fl.carrier_id;
ENDMETHOD.
METHOD get_carr_fli
BY DATABASE FUNCTION
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zdemo_abap_carr_ve zdemo_abap_flsch_ve.
* AMDP table function to be called by other AMDP methods only.
* In the example, joined data from two CDS view entities are returned.
RETURN
SELECT ca.carrname, fl.connid, fl.cityfrom, fl.cityto
FROM zdemo_abap_carr_ve as ca
INNER JOIN zdemo_abap_flsch_ve as fl
ON ca.carrid = fl.carrid
WHERE fl.carrid = :carrid
ORDER BY ca.mandt, ca.carrname, fl.connid;
ENDMETHOD.
METHOD get_flights
BY DATABASE PROCEDURE
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zcl_demo_abap_amdp=>get_flights_amdp.
* Another AMDP procedure is called from SQLScript
CALL "ZCL_DEMO_ABAP_AMDP=>GET_FLIGHTS_AMDP"(
carrid => :carrid,
fli_tab => :fli_tab );
ENDMETHOD.
METHOD get_flights_amdp
BY DATABASE PROCEDURE
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zdemo_abap_fli_ve.
* Simple data selection
fli_tab = SELECT carrid, connid, fldate, price, currency, planetype,
seatsmax, seatsocc, paymentsum, seatsmax_b, seatsocc_b,
seatsmax_f, seatsocc_f
FROM "ZDEMO_ABAP_FLI_VE"
WHERE carrid = :carrid
ORDER BY carrid;
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
out->write( `ABAP Cheat Sheet Example: AMDP` ).
out->write( |\n1) AMDP Procedure\n\n| ).
"Declaring an internal table to store the data that are
"returned by the following method.
"You could also choose to create the internal table inline
"within the method call,
"i. e. like ... IMPORTING carr_tab = DATA(tab) ).
DATA amdp_proc_res TYPE zcl_demo_abap_amdp=>carr_tab.
"Since the method is declared as an instance method, an instance
"has to be created. Here, the instance constructor NEW is used
"in a standalone method call that includes a chained method call.
NEW zcl_demo_abap_amdp( )->select_carriers(
IMPORTING carr_tab = amdp_proc_res ).
out->write( data = amdp_proc_res name = `amdp_proc_res` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `2) Calling an AMDP Procedure from SQLScript` ) ).
"As can be seen in the method implementation part, this AMDP procedure
"includes an AMDP procedure call from SQLScript.
"In this example, the AMDP procedure get_flights_amdp is called by
"get_flights which is meant to select data from a CDS view entity.
"The returned result is displayed.
TRY.
zcl_demo_abap_amdp=>get_flights( EXPORTING carrid = 'LH'
IMPORTING fli_tab = DATA(call_amdp_res) ).
CATCH cx_amdp_execution_error INTO DATA(error1).
out->write( error1->get_text( ) ).
ENDTRY.
out->write( data = call_amdp_res name = `call_amdp_res` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `3) AMDP Table Function for AMDP Method` ) ).
"The AMDP procedure select_get_carr_fli calls the AMDP table function
"get_carr_fli in the implementation part. AMDP table functions can
"only be called by other AMDP methods.
TRY.
NEW zcl_demo_abap_amdp( )->select_get_carr_fli(
EXPORTING carrid = 'LH'
IMPORTING carr_fli_tab = DATA(amdp_tab_func) ).
CATCH cx_amdp_execution_error INTO DATA(error2).
out->write( error2->get_text( ) ).
ENDTRY.
out->write( data = amdp_tab_func name = `amdp_tab_func` ).
"Note: When commented in, the following code results in a runtime
"error since you cannot call an AMDP function in ABAP directly.
* NEW zcl_demo_abap_amdp( )->get_carr_fli(
* EXPORTING carrid = 'LH' ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `4) AMDP Table Function for CDS Table Function` ) ).
"The example demonstrates that a CDS table function can be used as a
"data source of ABAP SQL read statements.
"You might want to navigate to the DDL source after FROM by holding
"CTRL and clicking the DDL source name in ADT to see the details.
"Or, just check out the F2 help.
"In this example, the CDS table function is implemented in a way to
"return accumulated data.
"In the method implementation for flight_analysis, first two kinds of
"data sets from two CDS view entities are gathered. These data sets are
"joined using an inner join. There, some expressions are included
"(strings are aggregated, average values are determined).
SELECT * FROM zdemo_abap_table_function
INTO TABLE @DATA(cds_tab_func).
out->write( data = cds_tab_func name = `cds_tab_func` ).
ENDMETHOD.
METHOD select_carriers
BY DATABASE PROCEDURE
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zdemo_abap_carr_ve.
* Simple data selection
carr_tab = SELECT carrid, carrname, currcode, url
FROM "ZDEMO_ABAP_CARR_VE"
ORDER BY carrid;
ENDMETHOD.
METHOD select_get_carr_fli
BY DATABASE PROCEDURE
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zcl_demo_abap_amdp=>get_carr_fli.
* AMDP procedure to call an AMDP table function as specified after USING
carr_fli_tab = SELECT *
FROM "ZCL_DEMO_ABAP_AMDP=>GET_CARR_FLI"(
carrid => :carrid );
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_AMDP</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: AMDP</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,718 @@
***********************************************************************
*
* Class for ABAP cheat sheet examples designed to clear and populate
* demo database tables
*
* -------------------------- NOTE -------------------------------------
* The code presented in this class is only meant for supporting the ABAP
* cheat sheets. It is not intended for direct use in a
* production system environment. The code examples in the ABAP cheat
* sheets are primarily intended to provide a better explanation and
* visualization of the syntax and semantics of ABAP statements and not to
* solve concrete programming tasks. For production application programs,
* a dedicated solution should therefore always be worked out for each
* individual case. There is no guarantee for either the correctness or
* the completeness of the code. In addition, there is no legal
* responsibility or liability for possible errors or their consequences
* which occur through the use of the example code.
*
***********************************************************************
"! <p class="shorttext synchronized">Class supporting ABAP cheat sheet examples</p>
"! The class supports the ABAP cheat examples by clearing and populating demo database tables that are used there.
"! The demo database tables contain airline and flight information.
CLASS zcl_demo_abap_aux DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
CLASS-METHODS: clear_dbtabs,
fill_dbtabs,
heading IMPORTING text TYPE string
RETURNING VALUE(output) TYPE string.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_demo_abap_aux IMPLEMENTATION.
METHOD clear_dbtabs.
DELETE FROM zdemo_abap_flsch.
DELETE FROM zdemo_abap_carr.
DELETE FROM zdemo_abap_fli.
ENDMETHOD.
METHOD fill_dbtabs.
"Clearing db tables before filling
clear_dbtabs( ).
"Filling db table
MODIFY zdemo_abap_flsch FROM TABLE @( VALUE #(
( carrid = 'AA'
connid = 0017
countryfr = 'US'
cityfrom = 'NEW YORK'
airpfrom = 'JFK'
countryto = 'US'
cityto = 'SAN FRANCISCO'
airpto = 'SFO'
fltime = 361
deptime = '110000'
arrtime = '140100'
distance = 2572
distid = 'MI'
fltype = ''
period = 0 )
( carrid = 'AA'
connid = 0064
countryfr = 'US'
cityfrom = 'SAN FRANCISCO'
airpfrom = 'SFO'
countryto = 'US'
cityto = 'NEW YORK'
airpto = 'JFK'
fltime = 321
deptime = '090000'
arrtime = '172100'
distance = 2572
distid = 'MI'
fltype = ''
period = 0 )
( carrid = 'AZ'
connid = 0555
countryfr = 'IT'
cityfrom = 'ROME'
airpfrom = 'FCO'
countryto = 'DE'
cityto = 'FRANKFURT'
airpto = 'FRA'
fltime = 125
deptime = '190000'
arrtime = '210500'
distance = 845
distid = 'MI'
fltype = ''
period = 0 )
( carrid = 'AZ'
connid = 0788
countryfr = 'IT'
cityfrom = 'ROME'
airpfrom = 'FCO'
countryto = 'JP'
cityto = 'TOKYO'
airpto = 'TYO'
fltime = 775
deptime = '120000'
arrtime = '085500'
distance = 6130
distid = 'MI'
fltype = ''
period = 1 )
( carrid = 'AZ'
connid = 0789
countryfr = 'JP'
cityfrom = 'TOKYO'
airpfrom = 'TYO'
countryto = 'IT'
cityto = 'ROME'
airpto = 'FCO'
fltime = 940
deptime = '114500'
arrtime = '192500'
distance = 6130
distid = 'MI'
fltype = ''
period = 0 )
( carrid = 'AZ'
connid = 0790
countryfr = 'IT'
cityfrom = 'ROME'
airpfrom = 'FCO'
countryto = 'JP'
cityto = 'OSAKA'
airpto = 'KIX'
fltime = 815
deptime = '103500'
arrtime = '081000'
distance = 6030
distid = 'MI'
fltype = 'X'
period = 1 )
( carrid = 'DL'
connid = 0106
countryfr = 'US'
cityfrom = 'NEW YORK'
airpfrom = 'JFK'
countryto = 'DE'
cityto = 'FRANKFURT'
airpto = 'FRA'
fltime = 475
deptime = '193500'
arrtime = '093000'
distance = 3851
distid = 'MI'
fltype = ''
period = 1 )
( carrid = 'DL'
connid = 1699
countryfr = 'US'
cityfrom = 'NEW YORK'
airpfrom = 'JFK'
countryto = 'US'
cityto = 'SAN FRANCISCO'
airpto = 'SFO'
fltime = 382
deptime = '171500'
arrtime = '203700'
distance = 2572
distid = 'MI'
fltype = ''
period = 0 )
( carrid = 'DL'
connid = 1984
countryfr = 'US'
cityfrom = 'SAN FRANCISCO'
airpfrom = 'SFO'
countryto = 'US'
cityto = 'NEW YORK'
airpto = 'JFK'
fltime = 325
deptime = '100000'
arrtime = '182500'
distance = 2572
distid = 'MI'
fltype = ''
period = 0 )
( carrid = 'JL'
connid = 0407
countryfr = 'JP'
cityfrom = 'TOKYO'
airpfrom = 'NRT'
countryto = 'DE'
cityto = 'FRANKFURT'
airpto = 'FRA'
fltime = 725
deptime = '133000'
arrtime = '173500'
distance = 9100
distid = 'KM'
fltype = ''
period = 0 )
( carrid = 'JL'
connid = 0408
countryfr = 'DE'
cityfrom = 'FRANKFURT'
airpfrom = 'FRA'
countryto = 'JP'
cityto = 'TOKYO'
airpto = 'NRT'
fltime = 675
deptime = '202500'
arrtime = '154000'
distance = 9100
distid = 'KM'
fltype = 'X'
period = 1 )
( carrid = 'LH'
connid = 0400
countryfr = 'DE'
cityfrom = 'FRANKFURT'
airpfrom = 'FRA'
countryto = 'US'
cityto = 'NEW YORK'
airpto = 'JFK'
fltime = 444
deptime = '101000'
arrtime = '113400'
distance = 6162
distid = 'KM'
fltype = ''
period = 0 )
( carrid = 'LH'
connid = 0401
countryfr = 'US'
cityfrom = 'NEW YORK'
airpfrom = 'JFK'
countryto = 'DE'
cityto = 'FRANKFURT'
airpto = 'FRA'
fltime = 435
deptime = '183000'
arrtime = '074500'
distance = 6162
distid = 'KM'
fltype = ''
period = 1 )
( carrid = 'LH'
connid = 0402
countryfr = 'DE'
cityfrom = 'FRANKFURT'
airpfrom = 'FRA'
countryto = 'US'
cityto = 'NEW YORK'
airpto = 'JFK'
fltime = 455
deptime = '133000'
arrtime = '150500'
distance = 6162
distid = 'KM'
fltype = 'X'
period = 0 )
( carrid = 'LH'
connid = 2402
countryfr = 'DE'
cityfrom = 'FRANKFURT'
airpfrom = 'FRA'
countryto = 'DE'
cityto = 'BERLIN'
airpto = 'SXF'
fltime = 65
deptime = '103000'
arrtime = '113500'
distance = 555
distid = 'KM'
fltype = ''
period = 0 ) ) ).
"Filling db table
MODIFY zdemo_abap_carr FROM TABLE @( VALUE #(
( carrid = 'AA'
carrname = 'American Airlines'
currcode = 'USD'
url = 'http://www.aa.com' )
( carrid = 'LH'
carrname = 'Lufthansa'
currcode = 'EUR'
url = 'http://www.lufthansa.com' )
( carrid = 'JL'
carrname = 'Japan Airlines'
currcode = 'JPY'
url = 'http://www.jal.co.jp' )
( carrid = 'DL'
carrname = 'Delta Airlines'
currcode = 'USD'
url = 'http://www.delta-air.com' )
( carrid = 'AZ'
carrname = 'ITA Airways'
currcode = 'EUR'
url = 'http://www.ita-airways.com' ) ) ).
"Filling db table
MODIFY zdemo_abap_fli FROM TABLE @( VALUE #(
( carrid = 'AA'
connid = 0017
fldate = '20230923'
price = '464.35'
currency = 'USD'
planetype = '747-400'
seatsmax = 385
seatsocc = 369
paymentsum = '191993.87'
seatsmax_b = 31
seatsocc_b = 31
seatsmax_f = 21
seatsocc_f = 19 )
( carrid = 'AA'
connid = 0017
fldate = '20230929'
price = '464.35'
currency = 'USD'
planetype = '747-400'
seatsmax = 385
seatsocc = 372
paymentsum = '193537.52'
seatsmax_b = 31
seatsocc_b = 30
seatsmax_f = 21
seatsocc_f = 20 )
( carrid = 'AA'
connid = 0017
fldate = '20231111'
price = '464.35'
currency = 'USD'
planetype = '747-400'
seatsmax = 385
seatsocc = 374
paymentsum = '193651.77'
seatsmax_b = 31
seatsocc_b = 29
seatsmax_f = 21
seatsocc_f = 21 )
( carrid = 'AA'
connid = 0064
fldate = '20220131'
price = '464.35'
currency = 'USD'
planetype = 'A340-600'
seatsmax = 330
seatsocc = 313
paymentsum = '168469.88'
seatsmax_b = 30
seatsocc_b = 30
seatsmax_f = 20
seatsocc_f = 19 )
( carrid = 'AA'
connid = 0064
fldate = '20220215'
price = '464.35'
currency = 'USD'
planetype = 'A340-600'
seatsmax = 330
seatsocc = 157
paymentsum = '84846.15'
seatsmax_b = 30
seatsocc_b = 15
seatsmax_f = 20
seatsocc_f = 10 )
( carrid = 'AZ'
connid = 0555
fldate = '20230721'
price = '226.41'
currency = 'EUR'
planetype = 'A319-100'
seatsmax = 120
seatsocc = 114
paymentsum = '26519.75'
seatsmax_b = 8
seatsocc_b = 8
seatsmax_f = 8
seatsocc_f = 8 )
( carrid = 'AZ'
connid = 0555
fldate = '20230728'
price = '226.41'
currency = 'EUR'
planetype = 'A319-100'
seatsmax = 120
seatsocc = 115
paymentsum = '16695.50'
seatsmax_b = 8
seatsocc_b = 8
seatsmax_f = 8
seatsocc_f = 8 )
( carrid = 'AZ'
connid = 0788
fldate = '20230922'
price = '1071.41'
currency = 'EUR'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 456
paymentsum = '548722.20'
seatsmax_b = 30
seatsocc_b = 30
seatsmax_f = 20
seatsocc_f = 20 )
( carrid = 'AZ'
connid = 0788
fldate = '20230722'
price = '1071.41'
currency = 'EUR'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 455
paymentsum = '544674.30'
seatsmax_b = 30
seatsocc_b = 28
seatsmax_f = 20
seatsocc_f = 20 )
( carrid = 'AZ'
connid = 0789
fldate = '20231025'
price = '1071.41'
currency = 'EUR'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 455
paymentsum = '545704.30'
seatsmax_b = 30
seatsocc_b = 30
seatsmax_f = 20
seatsocc_f = 19 )
( carrid = 'AZ'
connid = 0789
fldate = '20230221'
price = '1071.41'
currency = 'EUR'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 459
paymentsum = '549226.90'
seatsmax_b = 30
seatsocc_b = 30
seatsmax_f = 20
seatsocc_f = 20 )
( carrid = 'AZ'
connid = 0790
fldate = '20231228'
price = '1055.41'
currency = 'EUR'
planetype = '747-400'
seatsmax = 385
seatsocc = 370
paymentsum = '462373.86'
seatsmax_b = 31
seatsocc_b = 30
seatsmax_f = 21
seatsocc_f = 21 )
( carrid = 'AZ'
connid = 0790
fldate = '20231201'
price = '1055.41'
currency = 'EUR'
planetype = '747-400'
seatsmax = 385
seatsocc = 367
paymentsum = '463661.64'
seatsmax_b = 31
seatsocc_b = 31
seatsmax_f = 21
seatsocc_f = 21 )
( carrid = 'DL'
connid = 0106
fldate = '20230209'
price = '652.42'
currency = 'USD'
planetype = 'A340-600'
seatsmax = 330
seatsocc = 178
paymentsum = '136750.33'
seatsmax_b = 30
seatsocc_b = 17
seatsmax_f = 20
seatsocc_f = 10 )
( carrid = 'DL'
connid = 0106
fldate = '20240102'
price = '652.42'
currency = 'USD'
planetype = 'A340-600'
seatsmax = 330
seatsocc = 16
paymentsum = '12892.33'
seatsmax_b = 30
seatsocc_b = 2
seatsmax_f = 20
seatsocc_f = 10 )
( carrid = 'DL'
connid = 1699
fldate = '20230921'
price = '464.35'
currency = 'USD'
planetype = '767-200'
seatsmax = 260
seatsocc = 250
paymentsum = '126636.91'
seatsmax_b = 21
seatsocc_b = 20
seatsmax_f = 11
seatsocc_f = 11 )
( carrid = 'DL'
connid = 1699
fldate = '20230511'
price = '464.35'
currency = 'USD'
planetype = '767-200'
seatsmax = 260
seatsocc = 251
paymentsum = '126493.06'
seatsmax_b = 21
seatsocc_b = 20
seatsmax_f = 11
seatsocc_f = 11 )
( carrid = 'DL'
connid = 1984
fldate = '20230719'
price = '464.35'
currency = 'USD'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 460
paymentsum = '225427.35'
seatsmax_b = 30
seatsocc_b = 29
seatsmax_f = 20
seatsocc_f = 19 )
( carrid = 'DL'
connid = 1984
fldate = '20230213'
price = '464.35'
currency = 'USD'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 458
paymentsum = '225088.83'
seatsmax_b = 30
seatsocc_b = 30
seatsmax_f = 20
seatsocc_f = 19 )
( carrid = 'JL'
connid = 0407
fldate = '20231128'
price = '1102.77'
currency = 'JPY'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 458
paymentsum = '563231.65'
seatsmax_b = 30
seatsocc_b = 27
seatsmax_f = 20
seatsocc_f = 20 )
( carrid = 'JL'
connid = 0407
fldate = '20231019'
price = '1102.77'
currency = 'JPY'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 452
paymentsum = '553552.12'
seatsmax_b = 30
seatsocc_b = 28
seatsmax_f = 20
seatsocc_f = 19 )
( carrid = 'JL'
connid = 0408
fldate = '20231128'
price = '1102.77'
currency = 'JPY'
planetype = '747-400'
seatsmax = 385
seatsocc = 365
paymentsum = '470129.20'
seatsmax_b = 31
seatsocc_b = 28
seatsmax_f = 21
seatsocc_f = 20 )
( carrid = 'JL'
connid = 0408
fldate = '20230123'
price = '1102.77'
currency = 'JPY'
planetype = '747-400'
seatsmax = 385
seatsocc = 372
paymentsum = '487715.90'
seatsmax_b = 31
seatsocc_b = 31
seatsmax_f = 21
seatsocc_f = 20 )
( carrid = 'LH'
connid = 0400
fldate = '20230628'
price = '1184.54'
currency = 'EUR'
planetype = 'A340-600'
seatsmax = 330
seatsocc = 319
paymentsum = '270822.24'
seatsmax_b = 30
seatsocc_b = 30
seatsmax_f = 20
seatsocc_f = 20 )
( carrid = 'LH'
connid = 0400
fldate = '20230323'
price = '1184.54'
currency = 'EUR'
planetype = 'A340-600'
seatsmax = 330
seatsocc = 312
paymentsum = '262597.14'
seatsmax_b = 30
seatsocc_b = 28
seatsmax_f = 20
seatsocc_f = 19 )
( carrid = 'LH'
connid = 0401
fldate = '20231128'
price = '669.20'
currency = 'EUR'
planetype = '767-200'
seatsmax = 260
seatsocc = 246
paymentsum = '195417.72'
seatsmax_b = 21
seatsocc_b = 19
seatsmax_f = 11
seatsocc_f = 10 )
( carrid = 'LH'
connid = 0401
fldate = '20231229'
price = '669.20'
currency = 'EUR'
planetype = '767-200'
seatsmax = 260
seatsocc = 252
paymentsum = '199300.50'
seatsmax_b = 21
seatsocc_b = 19
seatsmax_f = 11
seatsocc_f = 11 )
( carrid = 'LH'
connid = 0402
fldate = '20230617'
price = '669.20'
currency = 'EUR'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 461
paymentsum = '353526.12'
seatsmax_b = 30
seatsocc_b = 29
seatsmax_f = 20
seatsocc_f = 18 )
( carrid = 'LH'
connid = 0402
fldate = '20230313'
price = '669.20'
currency = 'EUR'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 450
paymentsum = '349223.76'
seatsmax_b = 30
seatsocc_b = 29
seatsmax_f = 20
seatsocc_f = 19 )
( carrid = 'LH'
connid = 2402
fldate = '20231028'
price = '245.20'
currency = 'EUR'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 451
paymentsum = '127197.62'
seatsmax_b = 30
seatsocc_b = 29
seatsmax_f = 20
seatsocc_f = 19 )
( carrid = 'LH'
connid = 2402
fldate = '20231223'
price = '245.20'
currency = 'EUR'
planetype = 'A380-800'
seatsmax = 475
seatsocc = 458
paymentsum = '18944.86'
seatsmax_b = 30
seatsocc_b = 30
seatsmax_f = 20
seatsocc_f = 20 ) ) ).
ENDMETHOD.
METHOD heading.
output = |\n_________________________________________________________________________________\n\n{ text }\n\n|.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_AUX</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>Class supporting ABAP cheat sheet examples</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,481 @@
***********************************************************************
*
* ABAP cheat sheet: CDS View Entities
*
* -------------------------- PURPOSE ----------------------------------
* - Example to demonstrate CDS view entities. See the CDS view entities
* that are used in the example for more details.
* - Topics covered: Operands, expressions, and built-in functions in the
* element list of CDS view entities, input parameters, joins,
* associations
* - Note: In ADT, check out the CDS view entities used in this example
* by holding down CTRL and clicking on the CDS view entity. This will
* take you to the artifact. There you can choose F8 to open the data
* preview.
* ----------------------- GETTING STARTED -----------------------------
* - Open the class with the ABAP development tools for Eclipse (ADT).
* - Choose F9 to run the class.
* - Check the console output.
* - To understand the context and the ABAP syntax used, refer to the
* notes included in the class as comments or refer to the respective
* topic in the ABAP Keyword Documentation.
* - Due to the amount of console output, the examples contain numbers
* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections.
* Also, the variable name is displayed in most cases. So to find
* the relevant output in the console easier and faster, just search
* for the number/variable name in the console (CTRL+F in the console)
* or use the debugger.
*
* ----------------------------- NOTE -----------------------------------
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: CDS view entities</p>
"! Example to demonstrate CDS view entities.<br>Choose F9 in ADT to run the class.
CLASS zcl_demo_abap_cds_ve DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES:
if_oo_adt_classrun.
CLASS-METHODS class_constructor.
protected section.
private section.
ENDCLASS.
CLASS ZCL_DEMO_ABAP_CDS_VE IMPLEMENTATION.
METHOD class_constructor.
"Filling demo database tables.
zcl_demo_abap_aux=>fill_dbtabs( ).
"Some more database table insertions for this particular example
MODIFY zdemo_abap_carr FROM TABLE @( VALUE #(
( carrid = 'SQ'
carrname = 'Singapore Airlines'
currcode = 'SGD'
url = 'http://www.singaporeair.com ' )
( carrid = 'QF'
carrname = 'Qantas Airways'
currcode = 'AUD'
url = 'http://www.qantas.com.au' ) ) ).
MODIFY zdemo_abap_flsch FROM TABLE @( VALUE #(
( carrid = 'UA'
connid = 3517
countryfr = 'DE'
cityfrom = 'FRANKFURT'
airpfrom = 'FRA'
countryto = 'US'
cityto = 'NEW YORK'
airpto = 'JFK'
fltime = 495
deptime = '104000'
arrtime = '125500'
distance = 6162
distid = 'KM'
fltype = ''
period = 0 ) ) ).
MODIFY zdemo_abap_fli FROM TABLE @( VALUE #( ( carrid = 'UA' ) ) ).
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
out->write( |ABAP Cheat Sheet Example: CDS view entities\n\n| ).
out->write( `1) Operands, expressions and built-in functions ` &&
|in a CDS view entity\n\n| ).
"The following ABAP SQL SELECT statement uses a CDS view entity as
"the data source. All data is retrieved. The sample CDS view entity
"uses many operands, expressions and built-in functions to demonstrate
"various syntax options. In addition, the view contains an input
"parameter that must be provided with an actual parameter and
"specified in the ABAP SQL SELECT statement.
"In ADT, check out the CDS view entity by holding down CTRL and clicking
"on the CDS view entity. This will take you to the artifact. There you
"can choose F8 to open the data preview.
SELECT *
FROM zdemo_abap_cds_ve_sel( p_smax = 20 )
ORDER BY CarrierId
INTO TABLE @DATA(select_from_cds).
out->write( data = select_from_cds name = `select_from_cds` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `2) Aggregate Expressions` ) ).
"The following ABAP SQL SELECT statement uses a CDS view entity as
"the data source. All data is retrieved. The sample CDS view entity
"uses aggregate expressions.
SELECT *
FROM zdemo_abap_cds_ve_agg_exp
ORDER BY carrid
INTO TABLE @DATA(agg_expr).
out->write( data = agg_expr name = `agg_expr` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `3) Joins` ) ).
"The following ABAP SQL SELECT statement uses a CDS view entity as
"the data source. All data is retrieved. The sample CDS view entity
"contains multiple joins.
"The CDS view entity is designed to contain different join variants
"in one artifact. There, you can comment in/out code sections to
"check out the individual join variants. Therefore, the result of
"the following SELECT statement depends on which section you have
"commented in in the CDS view entity.
SELECT *
FROM zdemo_abap_cds_ve_joins
ORDER BY carrid
INTO TABLE @DATA(cds_joins).
out->write( data = cds_joins name = `cds_joins` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `4) Excursion: ABAP SQL and joins` ) ).
"The following ABAP SQL SELECT statements are intended to reproduce
"the different joins that are performed by the CDS view entity.
"Inner, left and right outer, and cross joins are covered. The data
"sources for the SELECT statements are the database tables.
"Note:
"- The prefix ~ is used in the ABAP SQL statements instead of . in
" the CDS view entity.
"- To demonstrate the handling of null values, some SELECT statements
" contain the coalesce function and CASE expressions similar to the
" CDS view entity.
out->write( `---------- Inner join ----------` ).
out->write( |\n| ).
out->write( |\n| ).
SELECT _carr~carrid,
_carr~carrname,
_flsch_in~cityfrom AS cityfr_in,
_flsch_in~cityto AS cityto_in
FROM zdemo_abap_carr AS _carr
INNER JOIN zdemo_abap_flsch AS _flsch_in
ON _carr~carrid = _flsch_in~carrid
ORDER BY _carr~carrid
INTO TABLE @DATA(sql_inner_join).
out->write( data = sql_inner_join name = `sql_inner_join` ).
out->write( |\n| ).
out->write( `---------- Left outer join ----------` ).
out->write( |\n| ).
out->write( |\n| ).
SELECT _carr~carrid,
_carr~carrname,
_flsch_lo~cityfrom AS cityfr_lo,
coalesce( _flsch_lo~cityto, '???' ) AS cityto_lo
FROM zdemo_abap_carr AS _carr
LEFT OUTER JOIN zdemo_abap_flsch AS _flsch_lo
ON _carr~carrid = _flsch_lo~carrid
ORDER BY _carr~carrid
INTO TABLE @DATA(sql_left_outer_join).
out->write( data = sql_left_outer_join name = `sql_left_outer_join` ).
out->write( |\n| ).
out->write( `---------- Right outer join ----------` ).
out->write( |\n| ).
out->write( |\n| ).
SELECT _carr~carrid,
_carr~carrname,
CASE WHEN _carr~url IS NOT NULL THEN _carr~url
ELSE '!!!'
END AS url_ro,
_flsch_ro~cityfrom AS cityfr_ro,
_flsch_ro~cityto AS cityto_ro
FROM zdemo_abap_carr AS _carr
RIGHT OUTER JOIN zdemo_abap_flsch AS _flsch_ro
ON _carr~carrid = _flsch_ro~carrid
ORDER BY _carr~carrid
INTO TABLE @DATA(sql_right_outer_join).
out->write( data = sql_right_outer_join name = `sql_right_outer_join` ).
out->write( |\n| ).
out->write( `---------- Cross join ----------` ).
out->write( |\n| ).
out->write( |\n| ).
SELECT _carr~carrid,
_carr~carrname,
_flsch_cr~cityfrom AS cityfr_cr,
_flsch_cr~cityto AS cityto_cr
FROM zdemo_abap_carr AS _carr
CROSS JOIN zdemo_abap_flsch AS _flsch_cr
ORDER BY _carr~carrid
INTO TABLE @DATA(sql_cross_join).
out->write( data = sql_cross_join name = `sql_cross_join` ).
out->write( |\n| ).
"Just a check what join example is currently commented in
IF cds_joins = sql_inner_join.
out->write( `In the example CDS view entity, the inner join example is commented in.` ).
ELSEIF cds_joins = sql_left_outer_join.
out->write( `In the example CDS view entity, the left outer join example is commented in.` ).
ELSEIF cds_joins = sql_right_outer_join.
out->write( `In the example CDS view entity, the right outer join example is commented in.` ).
ELSEIF cds_joins = sql_cross_join.
out->write( `In the example CDS view entity, the cross join example is commented in.` ).
ELSE.
out->write( `In the example CDS view entity, there is some other code present.` ).
ENDIF.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `Associations` ) ).
out->write( |5) Selecting data from a CDS view that contains associations\n\n| ).
"The following ABAP SQL SELECT statement uses a CDS view entity as
"the data source. All data is retrieved. The sample CDS view entity
"contains multiple associations.
"Some fields of some associations are used in the element list of the
"CDS view entity. This data is included in the result set. Some
"associations are exposed but no fields of those associations are
"included in the element list. Therefore, no join is instantiated on
"the database and no data from these exposed assocations is included
"in the result set.
SELECT *
FROM zdemo_abap_cds_ve_assoc
ORDER BY carrier
INTO TABLE @DATA(assoc).
out->write( data = assoc name = `assoc` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `Using exposed associations in ABAP SQL statements: ...` ) ).
"The following examples use path expressions to access the association
"targets of exposed associations.
out->write( |6) ... SELECT clause\n\n| ).
"The following ABAP SQL SELECT statement uses a CDS view entity as
"the data source. The statement uses an exposed association.
"The SELECT list contains fields from the exposed association. Only in
"this case (when a consumer, such as an ABAP SQL statement, requests
"data) is the join instantiated on the database.
"Note:
"- No attributes are specified for the path expression (attributes
" are covered in examples further down). In particular, a join type is
" not explicitly specified. In such a case, the join type depends on
" the place where the path expression is used. Since the path expression
" is used in the SELECT list of an ABAP SQL SELECT statement (where
" fields are specified), a LEFT OUTER JOIN is used by default.
"- The coalesce function is included for a field to handle null values.
SELECT carrier,
\_carr3-carrname,
coalesce( \_carr3-url, '###' ) AS cityto_lo
FROM zdemo_abap_cds_ve_assoc
ORDER BY carrier
INTO TABLE @DATA(assoc_exp_select).
out->write( data = assoc_exp_select name = `assoc_exp_select` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `7) ... FROM clause` ) ).
"The following ABAP SQL SELECT statement uses a CDS view entity as
"the data source. All data is retrieved.
"In this case, an exposed association is used in the FROM clause.
"Note:
"- No join type is explicitly specified. As mentioned above, the
" position of the path expression is important. In this case (when
" used in the FROM clause), an INNER JOIN is used by default.
"- You can open the data preview for the CDS view entity used and
" compare the result set with the output here. Due to the inner
" join, non-existent 'carrid' values in the association target are
" not contained in the result set.
SELECT *
FROM zdemo_abap_cds_ve_assoc\_carr3 AS _exp
ORDER BY carrid
INTO TABLE @DATA(assoc_exp_from).
out->write( data = assoc_exp_from name = `assoc_exp_from` ).
out->write( |\n| ).
"The following ABAP SQL SELECT statement is intended to reproduce
"the data retrieval as above.
"The statement uses the same CDS view entity as data source that
"is used by the CDS view entity above as data source.
"An inner join is performed on a database table (the _carr3
"association from above has this table defined as the association
"target in the CDS view entity) since the inner join is used by
"default above so as to reproduce the effect. The result set
"should be the same as above.
SELECT _carr~mandt,
_carr~carrid,
_carr~carrname,
_carr~currcode,
_carr~url
FROM zdemo_abap_cds_ve_assoc_e AS _cds
JOIN zdemo_abap_carr AS _carr ON _cds~carrid = _carr~carrid
ORDER BY _carr~carrid
INTO TABLE @DATA(sql_repr).
out->write( data = sql_repr name = `sql_repr` ).
out->write( |\n| ).
IF sql_repr = assoc_exp_from.
out->write( `The result sets are the same.` ).
ELSE.
out->write( `The result sets are differrent.` ).
ENDIF.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `8) ... Specifying attributes` ) ).
"The following ABAP SQL SELECT statement uses a CDS view entity as
"the data source. The statement uses an exposed association.
"The SELECT list contains a path expression that is specified with
"an attribute.
"Note:
"- Cardinality, join types, and filter conditions can be used as
" attributes.
"- In the example, only the cardinality is specified.
"- The cardinality can be specified to prevent syntax warnings/errors
" in cases where the cardinality of the association does not match
" the way it is used in a path expression.
"- The example does not explicitly specify a join type. As mentioned
" above, if not explicitly specified, the join type depends on where
" the path expression is used. Here, a column is specified in the
" SELECT list. This means that a LEFT OUTER JOIN is used by default.
"- The result set should contain an entry for 'UA' having an initial
" value for 'fldate'.
SELECT carrid,
connid,
cityfrom,
cityto,
"Without specifying the cardinality, the following warning
"occurs: Using association "_FLI" can increase the cardinality
"of the results set
"\_fli-fldate AS flightdate
\_fli[ (*) ]-fldate AS flightdate
"The specification above corresponds to the following specification
"that includes an explicit specification of LEFT OUTER
"\_fli[ (*) LEFT OUTER ]-fldate AS flightdate
FROM zdemo_abap_cds_ve_assoc_e
ORDER BY carrid, connid, flightdate
INTO TABLE @DATA(assoc_attr_card).
out->write( data = assoc_attr_card name = `assoc_attr_card` ).
out->write( |\n| ).
"Specifying the join type explicitly
"- INNER, LEFT/RIGHT OUTER are possible
"- The join type can only be specified together with the cardinality.
"- In the result set of the example, the 'UA' entry should not be
" contained.
SELECT carrid,
connid,
cityfrom,
cityto,
\_fli[ (*) INNER ]-fldate AS flightdate
FROM zdemo_abap_cds_ve_assoc_e
ORDER BY carrid, connid, flightdate
INTO TABLE @DATA(assoc_attr_joty).
out->write( data = assoc_attr_joty name = `assoc_attr_joty` ).
out->write( |\n| ).
"Specifying conditions
"- Filter conditions can be specified for the current association
"- The addition WHERE is optional in cases where the filter condition
" is the only attribute specified in the square brackets.
"- When the association is instantiated as a join, the filter condition
" is transformed into an extended condition for the join.
"- In the example, a specific 'carrid' value is filtered for. LEFT OUTER
" is specified as join type explicitly. Not specifying the join type here
" has the same effect. The 'fldate' value is only retrieved for 'DL'
" entries. The other ones have initial values.
SELECT carrid,
connid,
cityfrom,
cityto,
\_fli[ (*) LEFT OUTER WHERE carrid = 'DL' ]-fldate AS flightdate
"The following has the same effect in this example
"\_fli[ (*) WHERE carrid = 'DL' ]-fldate as flightdate
FROM zdemo_abap_cds_ve_assoc_e
ORDER BY carrid, connid, flightdate
INTO TABLE @DATA(assoc_attr_where).
out->write( data = assoc_attr_where name = `assoc_attr_where` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `9) ... WHERE clause` ) ).
"The following ABAP SQL SELECT statement uses a CDS view entity as
"the data source. The statement uses an exposed association.
"The SELECT list and the WHERE clause contain a path expression.
SELECT carrid,
connid,
countryfr,
countryto,
\_carr_exp-carrname
FROM zdemo_abap_cds_ve_assoc_e
WHERE \_carr_exp-carrid LIKE 'A_'
ORDER BY carrid, connid
INTO TABLE @DATA(assoc_exp_where).
out->write( data = assoc_exp_where name = `assoc_exp_where` ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_CDS_VE</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: CDS view entities</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_CLOUD_EXCURSION</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Excursions into ABAP for Cloud Development</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
CLASS local_class DEFINITION.
PUBLIC SECTION.
METHODS: constructor IMPORTING txt TYPE string,
double IMPORTING int TYPE
REF TO i RETURNING VALUE(res) TYPE i.
DATA: timestamp TYPE string,
text TYPE string.
CLASS-DATA: no_of_instances TYPE i READ-ONLY.
ENDCLASS.
CLASS local_class IMPLEMENTATION.
METHOD constructor.
"Number of instances of the class are counted.
no_of_instances = no_of_instances + 1.
"Set a time stamp.
DATA: ts TYPE timestampl.
GET TIME STAMP FIELD ts.
timestamp = |{ ts TIMESTAMP = SPACE }|.
text = |{ txt }, { sy-uname }.|.
ENDMETHOD.
METHOD double.
res = int->* * 2.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_CONSTRUCTOR_EXPR</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Constructor expressions</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,133 @@
"Note: This ABAP stopwatch is not intended to be used productively.
"The implementation is intended to be a playground for exploring
"time-related functions.
CLASS lcl_stopwatch DEFINITION.
PUBLIC SECTION.
CLASS-METHODS create
RETURNING
VALUE(sw_inst) TYPE REF TO lcl_stopwatch.
METHODS stop.
METHODS start.
METHODS store.
TYPES: BEGIN OF stored_times_struc,
interval TYPE i,
time_since_start TYPE string,
time_delta TYPE string,
END OF stored_times_struc.
TYPES stored_times_type TYPE SORTED TABLE OF stored_times_struc WITH UNIQUE KEY interval.
METHODS get_stored_times RETURNING VALUE(time) TYPE stored_times_type .
METHODS get_time RETURNING VALUE(time) TYPE string .
PROTECTED SECTION.
PRIVATE SECTION.
DATA time_start TYPE utclong.
DATA time_stop TYPE utclong.
DATA stopwatch_is_on TYPE abap_bool.
DATA interval_timer_is_on TYPE abap_bool.
TYPES: BEGIN OF time_struc,
days TYPE i,
hours TYPE i,
minutes TYPE int8,
seconds TYPE decfloat34,
END OF time_struc.
DATA time_elapsed TYPE time_struc.
TYPES cl2 TYPE c LENGTH 2.
DATA storage TYPE TABLE OF utclong WITH EMPTY KEY.
METHODS reset.
METHODS get_elapsed_time
IMPORTING start TYPE utclong
stop TYPE utclong
RETURNING VALUE(delta) TYPE time_struc.
METHODS time_output_prep
IMPORTING time TYPE time_struc
RETURNING VALUE(res) TYPE string.
ENDCLASS.
CLASS lcl_stopwatch IMPLEMENTATION.
METHOD create.
sw_inst = NEW #( ).
sw_inst->reset( ).
ENDMETHOD.
METHOD start.
"No multiple starts allowed
ASSERT stopwatch_is_on = abap_false.
ASSERT interval_timer_is_on = abap_false.
reset( ).
stopwatch_is_on = abap_true.
time_start = utclong_current( ).
ENDMETHOD.
METHOD stop.
ASSERT stopwatch_is_on = abap_true.
time_stop = utclong_current( ).
stopwatch_is_on = abap_false.
interval_timer_is_on = abap_false.
time_elapsed = get_elapsed_time( start = time_start
stop = time_stop ).
ENDMETHOD.
METHOD reset.
CLEAR: time_start,
time_stop,
time_elapsed,
stopwatch_is_on,
interval_timer_is_on,
storage.
ENDMETHOD.
METHOD get_elapsed_time.
cl_abap_utclong=>diff( EXPORTING high = stop
low = start
IMPORTING days = delta-days
hours = delta-hours
minutes = delta-minutes
seconds = delta-seconds ).
ENDMETHOD.
METHOD get_time.
"When the interval timer is on, it is not allowed to
"get the time. The get_stored_times method is to be used.
ASSERT interval_timer_is_on = abap_false.
IF stopwatch_is_on = abap_true.
stop( ).
ENDIF.
time = time_output_prep( time_elapsed ).
ENDMETHOD.
METHOD time_output_prep.
res = |{ COND #( WHEN time-days IS NOT INITIAL THEN time-days && ` days, ` ) }| &&
|{ COND #( WHEN numofchar( CONV cl2( time-hours ) ) = 1 THEN `0` && time-hours ELSE time-hours ) }:| &&
|{ COND #( WHEN numofchar( CONV cl2( time-minutes ) ) = 1 THEN `0` && time-minutes ELSE time-minutes ) }:| &&
|{ COND #( WHEN find( val = CONV string( time-seconds ) sub = `.` ) = 1 THEN `0` && time-seconds ELSE time-seconds ) }|.
ENDMETHOD.
METHOD store.
ASSERT stopwatch_is_on = abap_true.
interval_timer_is_on = abap_true.
APPEND utclong_current( ) TO storage.
ENDMETHOD.
METHOD get_stored_times.
IF interval_timer_is_on = abap_true.
stop( ).
ENDIF.
if lines( storage ) > 0.
LOOP AT storage REFERENCE INTO DATA(ref).
DATA(tabix) = sy-tabix.
DATA(time_since_start) = get_elapsed_time( start = time_start stop = ref->* ).
DATA(prep_time_since_start) = time_output_prep( time_since_start ).
DATA(time_delta) = get_elapsed_time( start = COND #( WHEN tabix = 1 THEN time_start ELSE storage[ tabix - 1 ] ) stop = ref->* ).
DATA(prep_time_delta) = time_output_prep( time_delta ).
INSERT VALUE #( interval = tabix
time_since_start = prep_time_since_start
time_delta = prep_time_delta ) INTO TABLE time.
ENDLOOP.
endif.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_DATE_TIME</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Date, Time, and Time Stamp</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_DTYPE_DOBJ</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Data Types and Data Objects</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,437 @@
CLASS lcl_det_at_runtime DEFINITION.
PUBLIC SECTION.
CLASS-DATA: string1 TYPE string,
string2 TYPE string,
string3 TYPE string,
dyn_meth_call_result TYPE string.
TYPES: type_p TYPE p LENGTH 8 DECIMALS 2, "elementary type
type_struc TYPE zdemo_abap_carr, "structure type
"internal table type
type_itab TYPE SORTED TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY carrid connid "primary key
WITH UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto, "secondary key
type_ref TYPE REF TO lcl_det_at_runtime. "reference type
TYPES: BEGIN OF struc_builtin,
builtin_type TYPE c LENGTH 10,
len TYPE i,
dec TYPE i,
END OF struc_builtin.
TYPES: BEGIN OF struc_dyn,
table TYPE string,
select_list TYPE string,
where_clause TYPE string_table,
order_by TYPE string,
target TYPE REF TO data,
rows TYPE i,
END OF struc_dyn.
CLASS-METHODS:
get_dyn_table_name RETURNING VALUE(tab) TYPE string,
get_dyn_dobj RETURNING VALUE(dobj) TYPE string,
get_dyn_field RETURNING VALUE(field) TYPE string,
get_dyn_select_list RETURNING VALUE(list) TYPE string,
get_dyn_where_clause RETURNING VALUE(clause_tab) TYPE string_table,
get_random_type RETURNING VALUE(random_type) TYPE string,
get_builtin_type RETURNING VALUE(builtin_type) TYPE struc_builtin,
get_dyn_class_meth EXPORTING cl TYPE string
meth TYPE string
ptab TYPE abap_parmbind_tab,
get_dyn_syntax_elements RETURNING VALUE(syntax_elements) TYPE struc_dyn,
fill_string.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS lcl_det_at_runtime IMPLEMENTATION.
METHOD get_dyn_table_name.
"Providing DDIC table names in a string table to be selected from.
DATA(flight_tables) = VALUE string_table(
( `ZDEMO_ABAP_CARR` ) ( `ZDEMO_ABAP_FLSCH` ) ( `ZDEMO_ABAP_FLI` ) ).
"Getting random number to determine the table index at runtime.
DATA(idx) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1
max = lines( flight_tables ) )->get_next( ).
"Returning parameter to receive the random table name.
tab = VALUE #( flight_tables[ idx ] DEFAULT `ZDEMO_ABAP_CARR` ).
ENDMETHOD.
METHOD get_builtin_type.
"Providing the names of built-in types in a string table to be selected from.
TYPES tabtyp TYPE TABLE OF struc_builtin-builtin_type WITH EMPTY KEY.
DATA(built) = VALUE tabtyp(
( 'd' )
( 'decfloat16' )
( 'decfloat34' )
( 'f' )
( 'i' )
( 'string' )
( 't' )
( 'xstring' )
( 'c' )
( 'n' )
( 'x' )
( 'p' )
).
"Getting random number to determine the table index at runtime
DATA(idx) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1
max = lines( built ) )->get_next( ).
"Providing the returning parameter with a random type name
TRY.
builtin_type = VALUE #( builtin_type = built[ idx ] dec = idx len = idx ).
CATCH cx_sy_itab_line_not_found.
builtin_type = VALUE #( builtin_type = `p` dec = 5 len = 5 ).
ENDTRY.
ENDMETHOD.
METHOD get_dyn_dobj.
"Providing strings with demo content
string1 = |Hallo, { sy-uname }. | &&
|This is string1.|.
string2 = |Hallo, { sy-uname }. | &&
|This is string2.|.
string3 = |Hallo, { sy-uname }. | &&
|This is string3.|.
"Filling table with data object names
DATA(str_tab) = VALUE string_table(
( `STRING1` ) ( `STRING2` ) ( `STRING3` ) ).
"Getting random number to determine the table index at runtime
DATA(idx) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1
max = lines( str_tab ) )->get_next( ).
"Providing the returning parameter with a random data object name
dobj = VALUE #( str_tab[ idx ] DEFAULT |Hallo, { sy-uname }. This is a string.| ).
ENDMETHOD.
METHOD get_dyn_field.
"Getting list of components of DDIC type zdemo_abap_carr
DATA(comp) = CAST cl_abap_structdescr(
cl_abap_typedescr=>describe_by_name(
'ZDEMO_ABAP_CARR' )
)->components.
"Getting random number to determine the table index at runtime;
"starting from 2 to exclude MANDT field
DATA(idx) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 2
max = lines( comp ) )->get_next( ).
"Providing the returning parameter with a random component name
field = VALUE #( comp[ idx ]-name DEFAULT `CARRID` ).
ENDMETHOD.
METHOD get_dyn_select_list.
"Providing SELECT lists in a string table to be selected from
DATA sel_list_tab TYPE string_table.
sel_list_tab = VALUE #(
( `CARRID, CONNID, COUNTRYFR, COUNTRYTO` )
( `CARRID, CONNID, CITYFROM, CITYTO` )
( `CARRID, CONNID, AIRPFROM, AIRPTO` )
( `CARRID, CONNID, AIRPFROM, AIRPTO, ` &&
`FLTIME, DEPTIME, ARRTIME, DISTANCE` )
).
"Getting random number to determine the table index at runtime
DATA(idx) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1
max = lines( sel_list_tab ) )->get_next( ).
"Providing the returning parameter with a random SELECT list
list = VALUE #( sel_list_tab[ idx ] DEFAULT `CARRID, CONNID, COUNTRYFR, COUNTRYTO` ).
ENDMETHOD.
METHOD get_dyn_where_clause.
"Providing WHERE clauses in a table to be selected from
DATA: BEGIN OF where_struc,
where_clause_tab TYPE string_table,
END OF where_struc.
DATA where_itab LIKE TABLE OF where_struc WITH EMPTY KEY.
where_itab = VALUE #(
( where_clause_tab = VALUE #( ( `CARRID = 'LH'` )
( `OR CARRID = 'AA'` ) ) )
( where_clause_tab = VALUE #( ( `CONNID BETWEEN 0 AND 300` ) ) )
( where_clause_tab = VALUE #( ( `CITYFROM LIKE '%FRA%'` ) ) )
( where_clause_tab =
VALUE #( ( `DISTANCE > 500 AND DISTID = 'KM'` ) ) ) ).
"Getting random number to determine the table index at runtime
DATA(idx) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1
max = lines( where_itab ) )->get_next( ).
"Providing the returning parameter with a random WHERE clause
clause_tab = VALUE #( where_itab[ idx ]-where_clause_tab DEFAULT VALUE #( ( `CARRID = 'LH'` ) ( `OR CARRID = 'AA'` ) ) ).
ENDMETHOD.
METHOD get_random_type.
"Providing names of classes in a string table to be selected from
"In this example, some types are defined in the public section
"of a local class. The class name is added here since the names
"are used in the global class.
DATA(str_tab) = VALUE string_table(
( `LCL_DET_AT_RUNTIME=>TYPE_P` )
( `LCL_DET_AT_RUNTIME=>TYPE_STRUC` )
( `LCL_DET_AT_RUNTIME=>TYPE_ITAB` )
( `LCL_DET_AT_RUNTIME=>TYPE_REF` )
( `LCL_DET_AT_RUNTIME` )
( `IF_OO_ADT_CLASSRUN` )
).
"Getting random number to determine the table index at runtime
DATA(idx) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1
max = lines( str_tab ) )->get_next( ).
"Providing the returning parameter with a random type name
random_type = VALUE #( str_tab[ idx ] DEFAULT `LCL_DET_AT_RUNTIME=>TYPE_STRUC` ).
ENDMETHOD.
METHOD get_dyn_class_meth.
"Providing class names in a string table to be selected from
DATA(class_tab) = VALUE string_table(
( `LCL_DEMO1` )
( `LCL_DEMO2` ) ).
"Getting random number to determine the table index at runtime
DATA(idx) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1
max = lines( class_tab ) )->get_next( ).
"Provide the exporting parameter with the random class name
cl = VALUE #( class_tab[ idx ] DEFAULT `LCL_DEMO1` ).
"Getting method names using RTTI
DATA(methods) = CAST cl_abap_classdescr( cl_abap_typedescr=>describe_by_name( cl ) )->methods.
"Getting random number to determine the table index at runtime
idx = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1
max = lines( methods ) )->get_next( ).
"Provide the exporting parameter with the random method name
meth = VALUE #( methods[ idx ]-name DEFAULT `METH_A` ).
"Data reference objects for the value parameter in the parameter table
DATA(ref_imp) = NEW string( `hi` ).
DATA(ref_exp) = NEW string( `hallo` ).
DATA(ref_ch) = NEW string( `salut` ).
DATA(ref_ret) = NEW string( `ciao` ).
"Filling the parameter tables
"Note: If the method signature has an importing parameter,
"it must be specified as exporting parameter here.
"Same is true for the exporting parameter in the signature
"that must be specified as importing parameter.
CASE meth.
WHEN `METH_A`.
ptab = VALUE #( ( name = 'A'
kind = cl_abap_objectdescr=>exporting
value = ref_exp )
( name = 'B'
kind = cl_abap_objectdescr=>importing
value = ref_imp ) ).
WHEN `METH_B`.
ptab = VALUE #( ( name = 'C'
kind = cl_abap_objectdescr=>changing
value = ref_ch )
( name = 'D'
kind = cl_abap_objectdescr=>returning
value = ref_ret ) ).
WHEN `METH_C`.
ptab = VALUE #( ( name = 'E'
kind = cl_abap_objectdescr=>exporting
value = ref_exp )
( name = 'F'
kind = cl_abap_objectdescr=>importing
value = ref_imp ) ).
WHEN `METH_D`.
ptab = VALUE #( ( name = 'G'
kind = cl_abap_objectdescr=>changing
value = ref_ch )
( name = 'H'
kind = cl_abap_objectdescr=>returning
value = ref_ret ) ).
ENDCASE.
ENDMETHOD.
METHOD fill_string.
dyn_meth_call_result = |Hallo { sy-uname }. The string was filled at { utclong_current( ) }.|.
ENDMETHOD.
METHOD get_dyn_syntax_elements.
"FROM clause
DATA(flight_tables) = VALUE string_table(
( `ZDEMO_ABAP_CARR` ) ( `ZDEMO_ABAP_FLSCH` ) ( `ZDEMO_ABAP_FLI` ) ).
"Getting random number to determine the table index at runtime.
DATA(idx_table) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( )
min = 1
max = lines( flight_tables ) )->get_next( ).
syntax_elements-table = VALUE #( flight_tables[ idx_table ] DEFAULT `ZDEMO_ABAP_CARR` ).
"SELECT list
DATA(comp) = CAST cl_abap_structdescr(
cl_abap_typedescr=>describe_by_name( syntax_elements-table ) )->components.
"At least 3 components
DATA(idx_comp) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( )
min = 3
max = lines( comp ) )->get_next( ).
DELETE comp FROM idx_comp + 1 TO lines( comp ).
LOOP AT comp ASSIGNING FIELD-SYMBOL(<comp>).
syntax_elements-select_list = syntax_elements-select_list && `, ` && <comp>-name.
ENDLOOP.
"Replacing initial comma
REPLACE PCRE `^,\s` IN syntax_elements-select_list WITH ``.
"WHERE clause
"Excluding the client field
DELETE comp WHERE name = 'MANDT'.
"A maximum of 4 fields are to be respected because that is the maximum of possible fields
"available in table zdemo_abap_carr (without the client field)
DATA(idx_where) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( )
min = 1
max = 4 )->get_next( ).
"In the example, the WHERE clause consists of an internal table of type string.
"The clause is set up with fields and only IS NOT INITIAL to be on the safe side for a
"somewhat 'meaningful' clause and in the interest of simplicity.
LOOP AT comp ASSIGNING FIELD-SYMBOL(<where>) TO idx_where.
IF sy-tabix = 1.
APPEND <where>-name && ` IS NOT INITIAL` TO syntax_elements-where_clause.
ELSE.
APPEND `OR ` && <where>-name && ` IS NOT INITIAL` TO syntax_elements-where_clause.
ENDIF.
ENDLOOP.
"ORDER BY clause
DATA(idx_order) = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( )
min = 1
max = lines( comp ) )->get_next( ).
syntax_elements-order_by = VALUE #( comp[ idx_order ]-name DEFAULT `CARRID` ).
"INTO clause
CREATE DATA syntax_elements-target TYPE TABLE OF (syntax_elements-table).
"UP TO ... ROWS
"A minimum of 2 and a maximum of 6 rows are to be retrieved by the SELECT statement
syntax_elements-rows = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( )
min = 2
max = 5 )->get_next( ).
ENDMETHOD.
ENDCLASS.
CLASS lcl_demo1 DEFINITION.
"Note that this is just a demo class with demo methods to work with in the example.
PUBLIC SECTION.
CLASS-METHODS:
meth_a IMPORTING a TYPE string
EXPORTING b TYPE string,
meth_b CHANGING c TYPE string
RETURNING VALUE(d) TYPE string.
ENDCLASS.
CLASS lcl_demo1 IMPLEMENTATION.
METHOD meth_a.
b = |Hallo from meth_a. '{ a }' was input.|.
"Filling an attribute for the output in the global class.
lcl_det_at_runtime=>dyn_meth_call_result = b.
ENDMETHOD.
METHOD meth_b.
c = `#` && c && `#`.
d = |Hallo from meth_b. Actual parameter of changing parameter: '{ c }'|.
"Filling an attribute for the output in the global class.
lcl_det_at_runtime=>dyn_meth_call_result = d.
ENDMETHOD.
ENDCLASS.
CLASS lcl_demo2 DEFINITION.
"Note that this is just a demo class with demo methods to work with in the example.
PUBLIC SECTION.
CLASS-METHODS:
meth_c IMPORTING e TYPE string
EXPORTING f TYPE string,
meth_d CHANGING g TYPE string
RETURNING VALUE(h) TYPE string.
ENDCLASS.
CLASS lcl_demo2 IMPLEMENTATION.
METHOD meth_c.
f = |Hallo from meth_c. '{ e }' was input.|.
"Filling an attribute for the output in the global class.
lcl_det_at_runtime=>dyn_meth_call_result = f.
ENDMETHOD.
METHOD meth_d.
g = `*` && g && `*`.
h = |Hallo from meth_d. Actual parameter of changing parameter: '{ g }'|.
"Filling an attribute for the output in the global class.
lcl_det_at_runtime=>dyn_meth_call_result = h.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_DYNAMIC_PROG</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Dynamic programming</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_INTERNAL_TABLES</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Internal tables</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,556 @@
*&--------------------------------------------------------------------*
*& Custom exception classes
*&--------------------------------------------------------------------*
CLASS cx_afternoon DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.
CLASS cx_night DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.
*&--------------------------------------------------------------------*
*& Class to demonstrate various method parameters
*& All formal parameters are passed by reference except the
*& returning parameter.
*&--------------------------------------------------------------------*
CLASS lcl_demo DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
"No parameters
hallo_static_ext,
"One importing parameter
powers_of_two IMPORTING i_pow TYPE i,
"Two importing parameters
"Specifying REFERENCE(p) is optional; a formal parameter
"without VALUE(p) or REFERENCE(p) is REFERENCE(p) by default
addition IMPORTING i_add1 TYPE i
REFERENCE(i_add2) TYPE i,
"Two importing parameters, one of them is optional.
addition_optional IMPORTING i_add_mand TYPE i
i_add_opt TYPE i OPTIONAL,
"Importing and exporting parameters
subtraction IMPORTING i_sub1 TYPE i
i_sub2 TYPE i
EXPORTING e_sub_result TYPE i,
"One exporting parameter
exporting_hallo EXPORTING text TYPE string,
"Changing parameter
square_root CHANGING i_sqr TYPE decfloat34,
"Importing and returning parameters
multiplication IMPORTING i_mult1 TYPE i
i_mult2 TYPE i
RETURNING VALUE(r_mult_result) TYPE i,
"Importing and exporting parameters
"for comparing the signature with method 'multiplication'
multiplication_exp_param IMPORTING i_multa TYPE i
i_multb TYPE i
EXPORTING e_mult_result TYPE i,
"Includes RAISING
division IMPORTING i_div1 TYPE i
i_div2 TYPE i
RETURNING VALUE(r_div_result) TYPE decfloat34
RAISING cx_sy_arithmetic_error,
check_daytime IMPORTING time TYPE t
EXPORTING greetings TYPE string
RAISING cx_afternoon cx_night,
"Include parameters with generic types
generic_data IMPORTING i_data TYPE data,
generic_tab IMPORTING i_anytab TYPE ANY TABLE.
CLASS-DATA: calc_result TYPE i,
string TYPE string,
some_data TYPE REF TO data.
ENDCLASS.
CLASS lcl_demo IMPLEMENTATION.
METHOD hallo_static_ext.
string = |Hallo { sy-uname }. | &&
|I'm a static method of class lcl_demo.|.
ENDMETHOD.
METHOD square_root.
i_sqr = sqrt( i_sqr ).
ENDMETHOD.
METHOD powers_of_two.
calc_result = i_pow * i_pow.
ENDMETHOD.
METHOD addition.
calc_result = i_add1 + i_add2.
ENDMETHOD.
METHOD addition_optional.
calc_result = i_add_mand + i_add_opt.
ENDMETHOD.
METHOD subtraction.
e_sub_result = i_sub1 - i_sub2.
ENDMETHOD.
METHOD exporting_hallo.
text = |Hallo { sy-uname }. | && |I'm a static method of class lcl_demo with one exporting parameter.|.
ENDMETHOD.
METHOD multiplication.
r_mult_result = i_mult1 * i_mult2.
ENDMETHOD.
METHOD multiplication_exp_param.
e_mult_result = i_multa * i_multb.
ENDMETHOD.
METHOD division.
CLEAR string.
TRY.
r_div_result = i_div1 / i_div2.
CATCH cx_sy_arithmetic_error INTO DATA(exc).
string = exc->get_text( ).
ENDTRY.
ENDMETHOD.
METHOD check_daytime.
CLEAR string.
"Morning: 5 am to 12 pm
IF time BETWEEN '050001' AND '120000'.
DATA(subrc) = 0.
ENDIF.
"Afternoon: 12 pm to 5 pm.
IF time BETWEEN '120001' AND '170000'.
subrc = 11.
ENDIF.
"Evening 5 pm to 9 pm.
"Commented out on purpose to have a time range for OTHERS :)
"IF time BETWEEN '170001' AND '210000'.
" subrc = 22.
"ENDIF.
"Night: 9 pm to 4 am.
IF time BETWEEN '210001' AND '235959' OR time BETWEEN '000000' AND '050000'.
subrc = 33.
ENDIF.
IF subrc <> 0.
CASE subrc.
WHEN 11.
greetings = |Good afternoon.|.
WHEN 33.
greetings = |Good night.|.
WHEN OTHERS.
greetings = |It's neither morning, afternoon or night. | &&
|Hence, wishing you a good evening.|.
ENDCASE.
ELSE.
greetings = |Good morning.|.
ENDIF.
ENDMETHOD.
METHOD generic_data.
"A data reference variable is created that has the type of the
"imported variable. Its content is store in the variable
"some_data in the public section to be able to access the content.
CREATE DATA some_data LIKE i_data.
some_data->* = i_data.
ENDMETHOD.
METHOD generic_tab.
"See implementation of generic_data.
"Here, an internal table is handled.
CREATE DATA some_data LIKE i_anytab.
some_data->* = i_anytab.
ENDMETHOD.
ENDCLASS.
*&--------------------------------------------------------------------*
*& Class to demonstrate basics in the global class
*&--------------------------------------------------------------------*
CLASS local_class DEFINITION.
PUBLIC SECTION.
METHODS: constructor.
DATA: num_inst TYPE i,
uuid TYPE sysuuid_x16,
timestamp TYPE timestampl.
CLASS-DATA: no_of_instances TYPE i READ-ONLY,
num_stat TYPE i VALUE 33.
CONSTANTS: const_number TYPE i VALUE 11.
TYPES type_i TYPE i.
ENDCLASS.
CLASS local_class IMPLEMENTATION.
METHOD constructor.
"Number of instances of the class are counted.
no_of_instances = no_of_instances + 1.
"Set a time stamp.
GET TIME STAMP FIELD timestamp.
"Increase the number.
num_inst = num_inst + 1.
"Get a random UUID.
TRY.
uuid = cl_system_uuid=>create_uuid_x16_static( ) .
CATCH cx_uuid_error.
ENDTRY.
ENDMETHOD.
ENDCLASS.
*&--------------------------------------------------------------------*
*& Class to demonstrate events
*&--------------------------------------------------------------------*
CLASS lcl_events DEFINITION.
PUBLIC SECTION.
DATA: greets TYPE string.
"Events declaration.
EVENTS: morning, afternoon, evening, night.
"Event handler methods
METHODS: morning_greets FOR EVENT morning OF lcl_events,
afternoon_greets FOR EVENT afternoon OF lcl_events,
evening_greets FOR EVENT evening OF lcl_events,
night_greets FOR EVENT night OF lcl_events.
"Method to raise events
METHODS: greetings.
ENDCLASS.
CLASS lcl_events IMPLEMENTATION.
METHOD greetings.
DATA(syst_time) = cl_abap_context_info=>get_system_time( ).
"Morning: 5 am to 12 pm
IF syst_time BETWEEN '050001' AND '120000'.
RAISE EVENT morning.
"Afternoon: 12 pm to 5 pm.
ELSEIF syst_time BETWEEN '120001' AND '170000'.
RAISE EVENT afternoon.
"Evening 5 pm to 9 pm.
ELSEIF syst_time BETWEEN '170001' AND '210000'.
RAISE EVENT evening.
"Night: 9 pm to 5 am.
ELSEIF syst_time BETWEEN '210001' AND '050000'.
RAISE EVENT night.
ENDIF.
ENDMETHOD.
METHOD morning_greets.
greets = |Good morning, { sy-uname }.|.
ENDMETHOD.
METHOD afternoon_greets.
greets = |Good afternoon, { sy-uname }.|.
ENDMETHOD.
METHOD evening_greets.
greets = |Good evening, { sy-uname }.|.
ENDMETHOD.
METHOD night_greets.
greets = |Good night, { sy-uname }.|.
ENDMETHOD.
ENDCLASS.
*&--------------------------------------------------------------------*
*& Class to demonstrate constructors
*&--------------------------------------------------------------------*
CLASS lcl_constructors DEFINITION.
PUBLIC SECTION.
METHODS: constructor IMPORTING num1 TYPE i
num2 TYPE i RAISING cx_sy_zerodivide.
DATA: uuid TYPE sysuuid_x16,
in_div_result TYPE i,
in_text TYPE string.
CLASS-METHODS: class_constructor,
add_1.
CLASS-DATA: no_of_instances TYPE i READ-ONLY,
stat_number TYPE i,
stat_text TYPE string.
ENDCLASS.
CLASS lcl_constructors IMPLEMENTATION.
METHOD constructor.
"Get time stamp.
DATA(ts1) = utclong_current( ).
"Provide message.
in_text = |The instance constructor of the class | &&
|lcl_constructors was called on { ts1 }.|.
"Count number of instances.
no_of_instances = no_of_instances + 1.
"Get random UUID.
TRY.
uuid = cl_system_uuid=>create_uuid_x16_static( ) .
CATCH cx_uuid_error.
ENDTRY.
CLEAR in_div_result.
"Do calculation.
in_div_result = num1 / num2.
ENDMETHOD.
METHOD class_constructor.
"Set a number.
stat_number = 999.
"Get time stamp.
DATA(ts2) = utclong_current( ).
"Provide message.
stat_text = |The static constructor of the class | &&
|lcl_constructors was called on { ts2 } and the | &&
|value for the variable 'stat_number' was set to | &&
|{ stat_number }.|.
ENDMETHOD.
METHOD add_1.
stat_number += 1.
ENDMETHOD.
ENDCLASS.
*&--------------------------------------------------------------------*
*& Classes to demonstrate inheritance, polymorphism and casting
*&--------------------------------------------------------------------*
"Class 1
CLASS lcl_class1 DEFINITION.
PUBLIC SECTION.
"Note: All methods are purposely included in the public section.
"Otherwise, it cannot be called in the demo's main class.
METHODS: constructor IMPORTING i_obj TYPE string OPTIONAL,
get_string RETURNING VALUE(str) TYPE string,
get_obj_name RETURNING VALUE(obj) TYPE string.
PRIVATE SECTION.
DATA: obj_name TYPE string.
ENDCLASS.
CLASS lcl_class1 IMPLEMENTATION.
METHOD constructor.
obj_name = i_obj.
ENDMETHOD.
METHOD get_obj_name.
obj = obj_name.
ENDMETHOD.
METHOD get_string.
str = `Hallo`.
ENDMETHOD.
ENDCLASS.
"Class 2a
CLASS lcl_class2a DEFINITION INHERITING FROM lcl_class1.
PUBLIC SECTION.
METHODS: get_string REDEFINITION,
get_number_2a RETURNING VALUE(num) TYPE i..
ENDCLASS.
CLASS lcl_class2a IMPLEMENTATION.
METHOD get_string.
str = |{ super->get_string( ) }, { sy-uname }!|.
ENDMETHOD.
METHOD get_number_2a.
num = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1 max = 100 )->get_next( ).
ENDMETHOD.
ENDCLASS.
"Class 2b
CLASS lcl_class2b DEFINITION INHERITING FROM lcl_class1 FINAL.
PUBLIC SECTION.
METHODS: get_string REDEFINITION,
get_number_2b RETURNING VALUE(num) TYPE i.
ENDCLASS.
CLASS lcl_class2b IMPLEMENTATION.
METHOD get_string.
str = |{ super->get_string( ) } from lcl_class2b, { sy-uname }!|.
ENDMETHOD.
METHOD get_number_2b.
num = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( ) min = 1 max = 100 )->get_next( ).
ENDMETHOD.
ENDCLASS.
"Class 3a
CLASS lcl_class3a DEFINITION INHERITING FROM lcl_class2a FINAL.
PUBLIC SECTION.
METHODS: get_string REDEFINITION.
ENDCLASS.
CLASS lcl_class3a IMPLEMENTATION.
METHOD get_string.
str = |{ super->get_string( ) } How are you doing?|.
ENDMETHOD.
ENDCLASS.
*&--------------------------------------------------------------------*
*& Classes to demonstrate a factory method in a singleton
*& and an abstract class.
*&--------------------------------------------------------------------*
"Using the addition CREATE PRIVATE, objects can only be created by the class itself.
CLASS lcl_singleton DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
METHODS: constructor,
"Methods for setting and getting a time stamp.
get_timestamp RETURNING VALUE(res_timestamp)
TYPE timestampl,
set_timestamp.
CLASS-METHODS:
"Factory method that returns an instance of the class.
get_instance RETURNING VALUE(res_instance) TYPE REF TO lcl_singleton.
CLASS-DATA: "Holds the number of overall instances.
no_of_instances TYPE i READ-ONLY.
PRIVATE SECTION.
CLASS-DATA: obj TYPE REF TO lcl_singleton.
DATA: timestamp TYPE timestampl.
ENDCLASS.
CLASS lcl_singleton IMPLEMENTATION.
METHOD get_instance.
"Checking if an instance of the class already exists.
"An instance should only be created if no instance exists
"to make sure that there is only a single instance overall.
IF obj IS NOT BOUND.
obj = NEW #( ).
ENDIF.
"In case an instance already exists, the existing one is
"always returned.
res_instance = obj.
ENDMETHOD.
METHOD constructor.
"Counts the number of instances of the class.
no_of_instances = no_of_instances + 1.
ENDMETHOD.
METHOD get_timestamp.
res_timestamp = timestamp.
ENDMETHOD.
METHOD set_timestamp.
GET TIME STAMP FIELD timestamp.
ENDMETHOD.
ENDCLASS.
CLASS lcl_sub DEFINITION DEFERRED.
CLASS lcl_abstract DEFINITION ABSTRACT.
PUBLIC SECTION.
CLASS-METHODS: factory_method IMPORTING check_num TYPE i
RETURNING VALUE(obj) TYPE REF TO lcl_abstract.
CLASS-DATA: message TYPE string.
"Abstract method: There's no implementation in this class.
METHODS: return_string ABSTRACT
IMPORTING i_str TYPE string
RETURNING VALUE(res_string) TYPE string.
ENDCLASS.
CLASS lcl_sub DEFINITION INHERITING FROM lcl_abstract.
PUBLIC SECTION.
METHODS: return_string REDEFINITION.
ENDCLASS.
CLASS lcl_abstract IMPLEMENTATION.
METHOD factory_method.
"Purpose of factory method: An instance can only be created
"if a certain condition is met.
CASE check_num.
WHEN 1.
obj = NEW lcl_sub( ).
message = `Great! I was able to create an instance.`.
WHEN OTHERS.
message = `What a pity. I'm not allowed to create an instance.`.
ENDCASE.
ENDMETHOD.
ENDCLASS.
CLASS lcl_sub IMPLEMENTATION.
METHOD return_string.
res_string = |I'm a returned string. | &&
|The object reference variable is { i_str }.|.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_OBJECTS</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: ABAP Object Orientation</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,46 @@
***********************************************************************
*
* Class supporting an ABAP cheat sheet example
*
* ----------------------------- NOTE -----------------------------------
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">Class supporting ABAP cheat sheet example</p>
"! The class supports the ABAP cheat sheet example about object orientation.
CLASS zcl_demo_abap_objects_friend DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS get_strings RETURNING VALUE(res_string) TYPE string_table.
protected section.
private section.
ENDCLASS.
CLASS ZCL_DEMO_ABAP_OBJECTS_FRIEND IMPLEMENTATION.
METHOD get_strings.
"Getting the strings and adding them to the string table.
"Accessing an attribute in a public visibility section.
APPEND zcl_demo_abap_objects=>public_string TO res_string.
"Accessing an attribute in a protected visibility section.
APPEND zcl_demo_abap_objects=>protected_string TO res_string.
"Accessing an attribute in a private visibility section.
APPEND zcl_demo_abap_objects=>private_string TO res_string.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_OBJECTS_FRIEND</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>Class for ABAP cheat sheet example</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
CLASS lcx_calc_error DEFINITION INHERITING FROM cx_no_check.
ENDCLASS.
CLASS lcx_some_error DEFINITION INHERITING FROM cx_no_check.
ENDCLASS.
CLASS lcx_invalid_email DEFINITION INHERITING FROM cx_no_check.
ENDCLASS.
CLASS lcx_static_exc_class DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_PROG_FLOW_LOGIC</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Program Flow Logic</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,514 @@
***********************************************************************
*
* RAP BO consumer for a RAP demo scenario
* ABAP EML in use: RAP calculator (managed, draft-enabled RAP BO with
* late numbering
*
* -------------------------- PURPOSE ----------------------------------
* - This class is the RAP BO consumer for a RAP demo scenario that
* represents a calculator using RAP concepts, i. e. using ABAP EML in
* the context of a managed and draft-enabled RAP business object with
* RAP late numbering to carry out simple calculations. Here, a RAP BO
* instance consists of a calculation ID (which is the key that is finally
* set not until the RAP save sequence), two operands (having integer
* values), the arithmetic operator and the result plus other
* draft-related fields.
* - Underlying data model: Consists of a root entity alone.
* The BDEF defines the behavior for this entity. The definitions in the
* BDEF determine which methods must be implemented in the ABAP behavior
* pool (ABP). Note that the view contains many annotations for the SAP
* Fiori UI.
* - ABP for this scenario: zbp_demo_abap_rap_draft_m
*
* ----------------------- GETTING STARTED (1) -------------------------
* ----------------- Using this class as RAP BO consumer ---------------
*
* - Open the class with the ABAP development tools for Eclipse (ADT).
* - Choose F9 to run the class.
* - Check the console output.
* - To understand the context and the ABAP syntax used, check the notes
* included in the class as comments or refer to the respective topic
* in the ABAP Keyword Documentation.
* - Due to the amount of output in the console, the examples include
* numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example
* sections. Plus, the variable name is displayed in most cases. Hence,
* to easier and faster find the relevant output in the console, just
* search in the console for the number/variable name (CTRL+F in the
* console) or use the debugger.
*
* ----------------------- GETTING STARTED (2) -------------------------
* Using the preview version of an SAP Fiori Elements UI as RAP BO consumer
*
* Create a service binding:
* 1. Find the service definition ZDEMO_ABAP_RAP_CALC_SD in the imported
* package in Business Services -> Service Definitions.
* 2. Right-click the service definition and choose New Service Binding.
* 3. In the New Service Binding pop-up, make the following entries:
* - Name: ZDEMO_ABAP_RAP_CALC_SB
* - Description: Service binding for demo
* - Binding type: OData V4 - UI
* - Service Definition: ZDEMO_ABAP_RAP_CALC_SD (should be already filled)
* 4. Choose Next.
* 5. Assign a transport request and choose Finish.
* 6. The service binding ZDEMO_ABAP_RAP_CALC_SB is opened. Activate the
* service binding.
* 7. In the Service Version Details section, choose the Publish button
* for the Local Service Endpoint. Once the service has been published,
* you should see ZDEMO_ABAP_RAP_DRAFT_M in the Entity Set and Association
* section.
* 8. Activate the service binding once the service has been published.
* 9. Select ZDEMO_ABAP_RAP_DRAFT_M and choose the Preview button.
* 10. The preview version of an SAP Fiori Elements app is displayed. If
* prompted, provide your credentials.
* 11. The app and the managed, draft-enabled RAP BO can be explored. If no
* columns are displayed, choose the 'Settings' button and select the
* desired columns.
* Choosing the 'Go' button refreshes the list. At first use, there
* might not be any entry. You can create an entry choosing the 'Create'
* button.
* The late numbering aspects enter the picture when you, for
* example, create a new instance, i. e. create a new calculation, and
* you keep a draft version of it instead of saving it to the database.
* The calculation ID which represents the key of the instance has an
* initial value. Only when you save the instance to the database, the
* final key is set.
* The effect of side effects can be explored as follows: Make an entry
* in an input field, click another input field (e.g. to make a new entry
* there), and check how the value for the result changes.
*
* ----------------------------- NOTE -----------------------------------
* This simplified example is not a real life scenario and rather
* focuses on the technical side by giving an idea how the communication
* and data exchange between a RAP BO consumer, which is a class
* in this case, and RAP BO provider can work. Additionally, it shows
* how the methods for non-standard RAP BO operations might be
* self-implemented in an ABP. The example is intentionally kept
* short and simple and focuses on specific RAP aspects. For this reason,
* the example might not fully meet the requirements of the RAP BO contract.
*
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: ABAP EML in a RAP scenario (draft BO)</p>
"! Example to demonstrate ABAP EML in the context of a RAP demo scenario (managed and draft-enabled RAP business object with RAP late numbering).
"! The class represents a RAP BO consumer.<br>Choose F9 in ADT to run the class.
CLASS zcl_demo_abap_rap_draft_ln_m DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_oo_adt_classrun.
CLASS-METHODS:
class_constructor.
protected section.
PRIVATE SECTION.
CLASS-DATA:
activate_tab TYPE TABLE FOR ACTION IMPORT
zdemo_abap_rap_draft_m~activate,
activate_tab2 TYPE TABLE FOR ACTION IMPORT
zdemo_abap_rap_draft_m~activate,
activate_tab3 TYPE TABLE FOR ACTION IMPORT
zdemo_abap_rap_draft_m~activate,
edit_tab TYPE TABLE FOR ACTION IMPORT
zdemo_abap_rap_draft_m~edit,
read_tab TYPE TABLE FOR READ IMPORT zdemo_abap_rap_draft_m,
f TYPE RESPONSE FOR FAILED zdemo_abap_rap_draft_m,
r TYPE RESPONSE FOR REPORTED zdemo_abap_rap_draft_m,
m TYPE RESPONSE FOR MAPPED zdemo_abap_rap_draft_m.
CLASS-METHODS:
initialize_dbtabs.
ENDCLASS.
CLASS ZCL_DEMO_ABAP_RAP_DRAFT_LN_M IMPLEMENTATION.
METHOD class_constructor.
initialize_dbtabs( ).
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
out->write( `ABAP Cheat Sheet Example: RAP Calculator Using Managed, ` &&
|Draft-Enabled RAP BO (Late Numbering)\n\n| ).
out->write( |1) Creating Instances and Saving to the database\n| ).
"Creating instances; draft indicator %is_draft is enabled
MODIFY ENTITY zdemo_abap_rap_draft_m
CREATE AUTO FILL CID
FIELDS ( num1 arithm_op num2 )
WITH VALUE #(
( %is_draft = if_abap_behv=>mk-on
num1 = 1 arithm_op = '+' num2 = 2 )
( %is_draft = if_abap_behv=>mk-on
num1 = 2 arithm_op = '*' num2 = 4 )
( %is_draft = if_abap_behv=>mk-on
num1 = 3 arithm_op = '-' num2 = 5 )
( %is_draft = if_abap_behv=>mk-on
num1 = 1 arithm_op = '/' num2 = 4 )
( %is_draft = if_abap_behv=>mk-on
num1 = 2 arithm_op = 'P' num2 = 5 ) )
FAILED f
REPORTED r
MAPPED m.
"Displaying responses only if FAILED and REPORTED
"response parameters are not initial
IF f IS NOT INITIAL OR r IS NOT INITIAL.
out->write( `Responses after MODIFY operation` ).
out->write( |\n| ).
IF m IS NOT INITIAL.
out->write( data = m name = `m` ).
out->write( |\n| ).
ENDIF.
IF f IS NOT INITIAL.
out->write( data = f name = `f` ).
out->write( |\n| ).
ENDIF.
IF r IS NOT INITIAL.
out->write( data = r name = `r` ).
out->write( |\n| ).
ENDIF.
ENDIF.
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
"Retrieving draft table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time, draftentitycreationdatetime,
draftentitylastchangedatetime
FROM zdemo_abap_draft
ORDER BY id
INTO TABLE @DATA(draft_parent_before_act).
"Retrieving database table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time
FROM zdemo_abap_tabca
ORDER BY id
INTO TABLE @DATA(db_tab_root_before_act).
"Filling the derived type for the ACTIVATE method by
"getting %pid values
LOOP AT m-calc
ASSIGNING FIELD-SYMBOL(<fs>).
APPEND VALUE #( %pid = <fs>-%pid )
TO activate_tab.
ENDLOOP.
MODIFY ENTITY zdemo_abap_rap_draft_m
EXECUTE activate AUTO FILL CID WITH activate_tab
MAPPED m
FAILED f
REPORTED r.
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
"Retrieving draft table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time, draftentitycreationdatetime,
draftentitylastchangedatetime
FROM zdemo_abap_draft
ORDER BY id
INTO TABLE @DATA(draft_parent_afer_act).
"Retrieving database table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time
FROM zdemo_abap_tabca
ORDER BY id
INTO TABLE @DATA(db_tab_root_after_act).
"Displaying entries
out->write( |1a) Draft and database tables before ACTIVATE action\n| ).
out->write( `Draft table before activation` ).
out->write( |\n| ).
out->write( data = draft_parent_before_act name = `draft_parent_before_act` ).
out->write( |\n| ).
out->write( `Database table before activation` ).
out->write( |\n| ).
out->write( data = db_tab_root_before_act name = `db_tab_root_before_act` ).
out->write( zcl_demo_abap_aux=>heading( `1b) Draft and database tables after ` &&
`ACTIVATE action` ) ).
out->write( `Draft table after activation` ).
out->write( |\n| ).
out->write( data = draft_parent_afer_act name = `draft_parent_afer_act` ).
out->write( |\n| ).
out->write( `Database table after activation` ).
out->write( |\n| ).
out->write( data = db_tab_root_after_act name = `db_tab_root_after_act` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `2) Creating Invalid Instances` ) ).
"Purposely creating invalid instances;
"draft indicator %is_draft is enabled
MODIFY ENTITY zdemo_abap_rap_draft_m
CREATE AUTO FILL CID
FIELDS ( num1 arithm_op num2 )
WITH VALUE #(
( %is_draft = if_abap_behv=>mk-on
num1 = 1 arithm_op = 'a' num2 = 1 ) "wrong operator
( %is_draft = if_abap_behv=>mk-on
num1 = 1 arithm_op = '/' num2 = 0 ) "0 division
( %is_draft = if_abap_behv=>mk-on
num1 = 2 arithm_op = 'P' num2 = 12345 ) ) "arithmetic overflow
FAILED f
REPORTED r
MAPPED m.
"Displaying responses only if FAILED and REPORTED
"response parameters are not initial.
IF f IS NOT INITIAL OR r IS NOT INITIAL.
out->write( data = `Responses after MODIFY operation` ).
out->write( |\n| ).
IF m IS NOT INITIAL.
out->write( data = m name = `m` ).
out->write( |\n| ).
ENDIF.
IF f IS NOT INITIAL.
out->write( data = f name = `f` ).
out->write( |\n| ).
ENDIF.
IF r IS NOT INITIAL.
out->write( data = r name = `r` ).
out->write( |\n| ).
ENDIF.
ENDIF.
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
"Retrieving draft table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time, draftentitycreationdatetime,
draftentitylastchangedatetime
FROM zdemo_abap_draft
ORDER BY id
INTO TABLE @draft_parent_before_act.
"Retrieving database table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time
FROM zdemo_abap_tabca
ORDER BY id
INTO TABLE @db_tab_root_before_act.
"Filling the derived type for the ACTIVATE method by
"getting %pid values; here, another table is filled for later use
LOOP AT m-calc
ASSIGNING FIELD-SYMBOL(<fs2>).
APPEND VALUE #( %pid = <fs2>-%pid )
TO activate_tab2.
APPEND VALUE #( %pid = <fs2>-%pid )
TO activate_tab3.
ENDLOOP.
MODIFY ENTITY zdemo_abap_rap_draft_m
EXECUTE activate AUTO FILL CID WITH activate_tab2
MAPPED m
FAILED f
REPORTED r.
"Displaying responses only if FAILED and REPORTED
"response parameters are not initial.
IF f IS NOT INITIAL OR r IS NOT INITIAL.
out->write( data = `Responses after MODIFY operation` ).
out->write( |\n| ).
IF m IS NOT INITIAL.
out->write( data = m name = `m` ).
out->write( |\n| ).
ENDIF.
IF f IS NOT INITIAL.
out->write( data = f name = `f` ).
out->write( |\n| ).
ENDIF.
IF r IS NOT INITIAL.
out->write( data = r name = `r` ).
out->write( |\n| ).
ENDIF.
ENDIF.
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
"Retrieving draft table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time, draftentitycreationdatetime,
draftentitylastchangedatetime
FROM zdemo_abap_draft
ORDER BY id
INTO TABLE @draft_parent_afer_act.
"Retrieving database table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time
FROM zdemo_abap_tabca
ORDER BY id
INTO TABLE @db_tab_root_after_act.
"Displaying entries
out->write( zcl_demo_abap_aux=>heading( `2a) Draft and database tables before ` &&
`ACTIVATE action` ) ).
out->write( `Draft table before activation` ).
out->write( |\n| ).
out->write( data = draft_parent_before_act name = `draft_parent_before_act` ).
out->write( |\n| ).
out->write( `Database table before activation` ).
out->write( |\n| ).
out->write( data = db_tab_root_before_act name = `db_tab_root_before_act` ).
out->write( zcl_demo_abap_aux=>heading( `2b) Draft and database tables after ` &&
`ACTIVATE action` ) ).
out->write( `Draft table after activation` ).
out->write( |\n| ).
out->write( data = draft_parent_afer_act name = `draft_parent_afer_act` ).
out->write( |\n| ).
out->write( `Database table after activation` ).
out->write( |\n| ).
out->write( data = db_tab_root_after_act name = `db_tab_root_after_act` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `3) Correcting and Updating Invalid Instances` ) ).
"Preparing the derived type for the read operation to
"retrieve the field values; the draft indicator is enabled
LOOP AT activate_tab3 ASSIGNING FIELD-SYMBOL(<fs3>).
APPEND VALUE #( %pky = <fs3>-%pky
%is_draft = if_abap_behv=>mk-on
%control-id = if_abap_behv=>mk-on
%control-num1 = if_abap_behv=>mk-on
%control-arithm_op = if_abap_behv=>mk-on
%control-num2 = if_abap_behv=>mk-on
%control-calc_result = if_abap_behv=>mk-on
%control-crea_date_time = if_abap_behv=>mk-on
%control-lchg_date_time = if_abap_behv=>mk-on
) TO read_tab.
ENDLOOP.
"Retrieving the entries of the invalid instances
READ ENTITY zdemo_abap_rap_draft_m
ALL FIELDS WITH read_tab
RESULT DATA(result).
"Correcting and updating the invalid instances
MODIFY ENTITY zdemo_abap_rap_draft_m
UPDATE FROM VALUE #(
FOR wa IN result (
%pid = wa-%pid
%is_draft = if_abap_behv=>mk-on
num2 = SWITCH #( wa-calc_result
WHEN `Division by 0` THEN 2
WHEN `Overflow error` THEN 3 )
arithm_op = SWITCH #( wa-calc_result
WHEN `Wrong operator` THEN '+' )
%control-num2 = SWITCH #( wa-calc_result
WHEN `Division by 0` THEN if_abap_behv=>mk-on
WHEN `Overflow error` THEN if_abap_behv=>mk-on
ELSE if_abap_behv=>mk-off )
%control-arithm_op = SWITCH #( wa-calc_result
WHEN `Wrong operator` THEN if_abap_behv=>mk-on
ELSE if_abap_behv=>mk-off ) ) )
FAILED f
REPORTED r
MAPPED m.
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
MODIFY ENTITY zdemo_abap_rap_draft_m
EXECUTE activate AUTO FILL CID WITH activate_tab3
MAPPED m
FAILED f
REPORTED r.
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
"Retrieving draft table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time, draftentitycreationdatetime,
draftentitylastchangedatetime
FROM zdemo_abap_draft
ORDER BY id
INTO TABLE @draft_parent_afer_act.
"Retrieving database table entries
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time,
lchg_date_time
FROM zdemo_abap_tabca
ORDER BY id
INTO TABLE @db_tab_root_after_act.
"Displaying entries
out->write( data = `Draft and database tables after ` &&
`ACTIVATE action` ).
out->write( |\n| ).
out->write( `Draft table after activation` ).
out->write( |\n| ).
out->write( data = draft_parent_afer_act name = `draft_parent_afer_act` ).
out->write( |\n| ).
out->write( `Database table after activation` ).
out->write( |\n| ).
out->write( data = db_tab_root_after_act name = `db_tab_root_after_act` ).
ENDMETHOD.
METHOD initialize_dbtabs.
DELETE FROM zdemo_abap_tabca.
DELETE FROM zdemo_abap_draft.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_RAP_DRAFT_LN_M</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: ABAP EML in a RAP scenario (draft BO)</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,23 @@
**********************************************************************
* Note:
*
* - This class is the RAP event handler class for zdemo_abap_rap_ro_m_as.
*
* - The RAP business events in this example are raised using RAISE
* ENTITY EVENT statements in the save_modified saver method that
* is implemented in the CCIMP include of the ABAP behavior pool
* zbp_demo_abap_rap_ro_m_as.
*
**********************************************************************
CLASS zcl_demo_abap_rap_evt_handler DEFINITION
PUBLIC ABSTRACT FINAL
FOR EVENTS OF zdemo_abap_rap_ro_m_as.
PUBLIC SECTION.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_demo_abap_rap_evt_handler IMPLEMENTATION.
ENDCLASS.

View File

@@ -0,0 +1,75 @@
CLASS lhe_event DEFINITION INHERITING FROM cl_abap_behavior_event_handler.
PRIVATE SECTION.
METHODS on_updated FOR ENTITY EVENT
updated FOR root~updated.
METHODS on_deleted FOR ENTITY EVENT
deleted FOR root~deleted.
METHODS on_created FOR ENTITY EVENT
created FOR root~created.
DATA evt_log TYPE TABLE OF zdemo_abap_draft WITH EMPTY KEY.
ENDCLASS.
CLASS lhe_event IMPLEMENTATION.
"Note:
"- For this example, database table entries are created for the individual
" RAP BO instances that are imported into the event handler methods.
"- The transactional phases are implicitly set when RAP business events are
" consumed locally. This means that RAP event handler methods are started in
" the modify phase when called. If database modifications are to be implemented
" in RAP event handler methods, you must explicitly activate the save phase to
" avoid causing errors detected by the controlled SAP LUW.
METHOD on_created.
cl_abap_tx=>save( ).
LOOP AT created ASSIGNING FIELD-SYMBOL(<created>).
TRY.
APPEND VALUE #( id = cl_system_uuid=>create_uuid_x16_static( )
draftuuid = cl_system_uuid=>create_uuid_x16_static( )
calc_result = |Instance key: "{ <created>-id }" / Event CREATED raised|
crea_date_time = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) )
) TO evt_log.
CATCH cx_uuid_error INTO DATA(err).
ASSERT err IS INITIAL.
ENDTRY.
MODIFY zdemo_abap_draft FROM TABLE @evt_log.
ENDLOOP.
ENDMETHOD.
METHOD on_updated.
cl_abap_tx=>save( ).
LOOP AT updated ASSIGNING FIELD-SYMBOL(<updated>).
TRY.
APPEND VALUE #( id = cl_system_uuid=>create_uuid_x16_static( )
draftuuid = cl_system_uuid=>create_uuid_x16_static( )
calc_result = |Instance key: "{ <updated>-id }" / %param: col1: "{ <updated>-%param-col1 }" col2: "{ <updated>-%param-col2 }"|
crea_date_time = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) )
) TO evt_log.
CATCH cx_uuid_error INTO DATA(err).
ASSERT err IS INITIAL.
ENDTRY.
MODIFY zdemo_abap_draft FROM TABLE @evt_log.
ENDLOOP.
ENDMETHOD.
METHOD on_deleted.
cl_abap_tx=>save( ).
LOOP AT deleted ASSIGNING FIELD-SYMBOL(<deleted>).
TRY.
APPEND VALUE #( id = cl_system_uuid=>create_uuid_x16_static( )
draftuuid = cl_system_uuid=>create_uuid_x16_static( )
calc_result = |Instance key: "{ <deleted>-id }" / %param: col1: "{ <deleted>-%param-col1 }" col2: "{ <deleted>-%param-col2 }"|
crea_date_time = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) )
) TO evt_log.
CATCH cx_uuid_error INTO DATA(err).
ASSERT err IS INITIAL.
ENDTRY.
MODIFY zdemo_abap_draft FROM TABLE @evt_log.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_RAP_EVT_HANDLER</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>RAP event handler class</DESCRIPT>
<CATEGORY>07</CATEGORY>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<CLSDEFINT>ZDEMO_ABAP_RAP_RO_M_AS</CLSDEFINT>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_RAP_EXT_NUM_M</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: ABAP EML in a RAP scenario (managed BO)</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_RAP_EXT_NUM_U</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: ABAP EML in a RAP scenario (unmanaged BO)</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,318 @@
***********************************************************************
*
* RAP BO consumer for a RAP demo scenario:
* Managed RAP BO with managed internal numbering and additional save
* demonstrating the local consumption of RAP business events
*
* -------------------------- PURPOSE ----------------------------------
* - Primarily, the example demonstrates the local consumption of RAP
* business events.
* - For that purpose, the BDEF defines three events. Two of them are
* specified with a parameter. The events are raised for create, update
* and delete operations.
* - The example implementation in this class (the RAP BO consumer)
* contains three ABAP EML modify requests: a RAP create, update and
* delete operation. For each of the operations, an event is raised
* using a RAISE ENTITY EVENT statement. The events are raised in the
* save_modified RAP saver method in the CCIMP include of the behavior
* pool.
* - When the events are raised, the RAP event handler methods are called
* asynchronously. To demonstrate the effect of the events, a database
* table representing a log table is populated.
* - In the output of the example, the content of internal tables is
* displayed to demonstrate the effect of the RAP operations by
* selecting from the database table where the RAP BO instances are
* persisted to after each RAP operation. Additionally, the content
* of an internal table is displayed including the entries that have been
* inserted into the log database table by the event handler methods.
* In this self-contained example, this 'log database table' is just a
* database table that is used to store some entries triggered by the RAP
* events for visualization purposes. You can imagine that, for example,
* the sending of an email is triggered there, or the application log is
* filled, and so on. The log table is used in another RAP example as
* draft table. The draft concept is not relevant for this simplified
* example here.
* - Note the comments in the example code. You can check out the
* asynchronity by commenting out the WAIT statement further down.
*
* ----------------- RELATED ARTIFACTS OF THE EXAMPLE ------------------*
* - RAP BO consumer: zcl_demo_abap_rap_m_as (this class here)
* - RAP BO provider (ABAP behavior pool): zbp_demo_abap_rap_ro_m_as
* - RAP event handler: zcl_demo_abap_rap_evt_handler
* - BDEF: zdemo_abap_rap_ro_m_as
* - More artifacts are related such as database tables, CDS views, and
* an abstract entity (zdemo_abap_abstract_ent; used for the parameter
* specifications for the events in the BDEF)
*
* ----------------------- GETTING STARTED -----------------------------
* - Open the class with the ABAP development tools for Eclipse (ADT).
* - Choose F9 to run the class.
* - Check the console output.
* - To understand the context and the ABAP syntax used, check the notes
* included in the class as comments or refer to the respective topic
* in the ABAP Keyword Documentation.
* - Due to the amount of output in the console, the examples include
* numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example
* sections. Plus, the variable name is displayed in most cases. Hence,
* to easier and faster find the relevant output in the console, just
* search in the console for the number/variable name (CTRL+F in the
* console) or use the debugger.
*
* ----------------------------- NOTE -----------------------------------
* This simplified example is not a real life scenario and rather
* focuses on the technical side by giving an idea how the communication
* and data exchange between a RAP BO consumer, which is a class
* in this case, and RAP BO provider can work. Additionally, it shows
* how the methods for non-standard RAP BO operations might be
* self-implemented in an ABP. The example is intentionally kept
* short and simple and focuses on specific RAP aspects. For this reason,
* the example might not fully meet the requirements of the RAP BO contract.
*
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: Local consumption of RAP Business Events</p>
"! Example to demonstrate local consumption of RAP business events in the context of a RAP demo scenario (managed RAP BO with managed internal numbering and additional save).
"! The class represents a RAP BO consumer.<br>Choose F9 in ADT to run the class.
CLASS zcl_demo_abap_rap_m_as DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_oo_adt_classrun.
CLASS-METHODS:
class_constructor.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_demo_abap_rap_m_as IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
out->write( |ABAP Cheat Sheet Example: Local Consumption of RAP Business Events\n\n| ).
"RAP create operation that creates multiple calculations
"Note the AUTO FILL CID addition with which the required %cid values
"for RAP BO instances are created automatically. Since the scenario is
"managed internal numbering, the 'id' field is assigned an appropriate value
"automatically by the RAP framework.
MODIFY ENTITY zdemo_abap_rap_ro_m_as
CREATE AUTO FILL CID
FIELDS ( num1 arithm_op num2 )
WITH VALUE #( ( num1 = 1
arithm_op = '+'
num2 = 2 )
( num1 = 5
arithm_op = '-'
num2 = 30 )
( num1 = 3
arithm_op = '*'
num2 = 3 )
( num1 = 7
arithm_op = '/'
num2 = 5 )
( num1 = 2
arithm_op = 'P'
num2 = 4 )
( num1 = 10
arithm_op = 'P'
num2 = 1000000000 )
( num1 = 2
arithm_op = '/'
num2 = 0 ) )
MAPPED DATA(m_cr)
FAILED DATA(f_cr)
REPORTED DATA(r_cr).
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
"Getting and displaying persisted instances to show the effect of the
"EML MODIFY statement
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time, lchg_date_time
FROM zdemo_abap_tabca
ORDER BY lchg_date_time
INTO TABLE @DATA(dbtab_entries).
out->write( `Database table entries after the create operation`
)->write( dbtab_entries
)->write( |\n| ).
**********************************************************************
"RAP update operation
"In the example, all RAP BO instances that were created above are
"updated. Here, the second number is updated with a random
"integer (from the value range 1 - 10). For this purpose, the
"cl_abap_random_int class is used.
"The reference to existing instances is made using entries in the
"mapped reponse table from above (it contains all keys of the created
"RAP BO instances).
IF m_cr-root IS NOT INITIAL.
MODIFY ENTITY zdemo_abap_rap_ro_m_as
UPDATE FIELDS ( num2 )
WITH VALUE #( FOR wa IN m_cr-root ( id = wa-id
num2 = cl_abap_random_int=>create(
seed = cl_abap_random=>seed( )
min = 1
max = 10 )->get_next( ) ) )
FAILED DATA(f_upd)
REPORTED DATA(r_upd).
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
"Getting and displaying persisted instances to show the effect of the
"EML MODIFY statement
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time, lchg_date_time
FROM zdemo_abap_tabca
ORDER BY lchg_date_time
INTO TABLE @dbtab_entries.
out->write( `Database table entries after the update operation`
)->write( dbtab_entries
)->write( |\n| ).
ENDIF.
**********************************************************************
"RAP delete operation
"As above, the reference to existing RAP BO instances is made
"using entries in the mapped response table. In the example,
"the first three instances created are deleted.
IF lines( m_cr-root ) > 3.
MODIFY ENTITY zdemo_abap_rap_ro_m_as
DELETE FROM VALUE #( ( id = m_cr-root[ 1 ]-id )
( id = m_cr-root[ 2 ]-id )
( id = m_cr-root[ 3 ]-id ) )
FAILED DATA(f_del)
REPORTED DATA(r_del).
COMMIT ENTITIES.
IF sy-subrc <> 0.
out->write( `An issue occurred in the RAP save sequence.` ).
ENDIF.
"Getting and displaying persisted instances to show the effect of the
"EML MODIFY statement
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time, lchg_date_time
FROM zdemo_abap_tabca
ORDER BY lchg_date_time
INTO TABLE @dbtab_entries.
out->write( `Database table entries after the delete operation`
)->write( dbtab_entries
)->write( |\n| ).
ENDIF.
**********************************************************************
"Note:
"- Due to the asynchronous call of the events, a WAIT statement
" is included to give the events some time in this self-contained example,
" i.e. so that all the database table entries that are created in the
" RAP event handler method can be retrieved and displayed.
"- In the RAP event handler method implementation, note the cl_abap_tx=>save( ).
" method call. This explicit activation of the 'save' transactional phase
" is required because, when called, the methods are started in the
" 'modify' transactional phase. In the modify phase, database modification
" statements are not allowed. If the save phase is not activated,
" a following database modification statement results in an error.
"To explore the asynchronity of the event raising, you can comment out the
"following WAIT statement.
WAIT UP TO 2 SECONDS.
DATA(tmstmp_after_wait) = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) ).
out->write( |Timestamp (e.g. for comparing with the timestamps of the events raised): { tmstmp_after_wait }| ).
out->write( |\n| ).
"The global class of the behavior pool contains a static attribute of type i.
"The example is implemented as follows: When events are raised in the save_modified
"method, this number is increased by 1 per event raised. The number represents
"the expected events to be raised. It is used in the following example implementation.
"As mentioned above, you can comment out the WAIT statement to potentially see
"a different number here compared to the number of entries in the log table.
out->write( |Number of expected events raised: { zbp_demo_abap_rap_ro_m_as=>num_raised_events }| ).
out->write( |\n| ).
"Getting and displaying database table entries that were inserted
"in the event handler method implementations to demonstrate that
"events have been triggered.
SELECT calc_result, crea_date_time
FROM zdemo_abap_draft
ORDER BY crea_date_time
INTO TABLE @DATA(evt_log_entries).
out->write( |Entries in log table at this stage (after SELECT from database table): { lines( evt_log_entries ) }| ).
out->write( |\n| ).
DATA(flag) = abap_false.
IF evt_log_entries IS INITIAL.
out->write( `There are no entries in the log table.` &&
` Try and run the example again.` ).
flag = abap_true.
ELSEIF lines( evt_log_entries ) BETWEEN 1 AND zbp_demo_abap_rap_ro_m_as=>num_raised_events - 1.
out->write( `Log database table entries created by the ` &&
`raised events` )->write( `Note that not all expected log database table entries have been created yet by the ` &&
`raised events`
)->write( evt_log_entries ).
flag = abap_true.
ELSE.
out->write( `Log database table entries created by the ` &&
`raised events`
)->write( evt_log_entries ).
ENDIF.
"The following implementation is included for exploring the asynchronity in the self-contained example, if you
"have commented out the WAIT statement above, or if not all expected entries are available in the database table
"yet. This is just to give it some more time and select from the database table again.
IF flag = abap_true.
out->write( |\n| ).
out->write( |******************************************************| ).
out->write( |\n| ).
out->write( |Out of { zbp_demo_abap_rap_ro_m_as=>num_raised_events } events that are expected to be raised in the example implementation, | &&
|only { lines( evt_log_entries ) } events are available in the database table at this stage. So, waiting a bit more ...| ).
out->write( |\n| ).
WAIT UP TO 1 SECONDS.
SELECT calc_result, crea_date_time
FROM zdemo_abap_draft
ORDER BY crea_date_time
INTO TABLE @evt_log_entries.
IF lines( evt_log_entries ) = zbp_demo_abap_rap_ro_m_as=>num_raised_events.
out->write( `Log database table entries created by the ` &&
`raised events after waiting some more time`
)->write( evt_log_entries ).
ELSE.
out->write( |Hmm... still not all events are available in the database table.| ).
out->write( evt_log_entries ).
ENDIF.
ENDIF.
ENDMETHOD.
METHOD class_constructor.
DELETE FROM zdemo_abap_tabca.
DELETE FROM zdemo_abap_draft.
CLEAR zbp_demo_abap_rap_ro_m_as=>num_raised_events.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_RAP_M_AS</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Local consumption of RAP Business Events</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_SQL</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: ABAP SQL</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,181 @@
***********************************************************************
*
* ABAP cheat sheet: ABAP SQL - Grouping Internal Tables
*
* -------------------------- PURPOSE ----------------------------------
* Example to demonstrate syntax options when grouping internal tables.
*
* ----------------------- GETTING STARTED -----------------------------
* - Open the class with the ABAP development tools for Eclipse (ADT).
* - Choose F9 to run the class.
* - Check the console output.
* - To understand the context and the ABAP syntax used, refer to the
* notes included in the class as comments or refer to the respective
* topic in the ABAP Keyword Documentation.
* - Due to the amount of console output, the examples contain numbers
* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections.
* Also, the variable name is displayed in most cases. So to find
* the relevant output in the console easier and faster, just search
* for the number/variable name in the console (CTRL+F in the console)
* or use the debugger.
*
* ----------------------------- NOTE -----------------------------------
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: ABAP SQL - Grouping internal tables</p>
"! Example to demonstrate grouping internal tables.<br>Choose F9 in ADT to run the class.
CLASS zcl_demo_abap_sql_group_by DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_oo_adt_classrun.
CLASS-METHODS: class_constructor.
protected section.
PRIVATE SECTION.
CLASS-DATA:
wa TYPE zdemo_abap_flsch,
member TYPE zdemo_abap_flsch,
members TYPE STANDARD TABLE OF zdemo_abap_flsch WITH EMPTY KEY.
ENDCLASS.
CLASS ZCL_DEMO_ABAP_SQL_GROUP_BY IMPLEMENTATION.
METHOD class_constructor.
"Fill demo database tables.
zcl_demo_abap_aux=>fill_dbtabs( ).
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
out->write( |ABAP Cheat Sheet Example: Grouping Internal Tables\n\n| ).
SELECT *
FROM zdemo_abap_flsch
INTO TABLE @DATA(fli_tab).
out->write( |1) Representative Binding\n| ).
out->write( |1a) Grouping by one column\n| ).
LOOP AT fli_tab INTO wa
GROUP BY wa-carrid.
out->write( wa-carrid ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `1b) Members of one column groups` ) ).
LOOP AT fli_tab INTO wa
GROUP BY wa-carrid.
CLEAR members.
LOOP AT GROUP wa INTO member.
members = VALUE #( BASE members ( member ) ).
ENDLOOP.
out->write( members ).
out->write( |\n| ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `1c) Grouping by two columns` ) ).
LOOP AT fli_tab INTO wa
GROUP BY ( key1 = wa-carrid key2 = wa-airpfrom ).
out->write( |{ wa-carrid } { wa-airpfrom }| ).
out->write( |\n| ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `1d) Members of two column groups` ) ).
LOOP AT fli_tab INTO wa
GROUP BY ( key1 = wa-carrid key2 = wa-airpfrom ).
CLEAR members.
LOOP AT GROUP wa INTO member.
members = VALUE #( BASE members ( member ) ).
ENDLOOP.
out->write( members ).
out->write( |\n| ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `2) Group Key Binding` ) ).
out->write( |2a) Grouping by one column\n| ).
LOOP AT fli_tab INTO wa
GROUP BY wa-carrid
INTO DATA(key).
out->write( key ).
out->write( |\n| ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `2b) Members of one column groups` ) ).
LOOP AT fli_tab INTO wa
GROUP BY wa-carrid
INTO key.
CLEAR members.
LOOP AT GROUP key INTO member.
members = VALUE #( BASE members ( member ) ).
ENDLOOP.
out->write( members ).
out->write( |\n| ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `2c) Grouping by two columns` ) ).
LOOP AT fli_tab INTO wa
GROUP BY ( key1 = wa-carrid key2 = wa-airpfrom )
INTO DATA(keys).
out->write( keys ).
out->write( |\n| ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `2d) Members of two column groups` ) ).
LOOP AT fli_tab INTO wa
GROUP BY ( key1 = wa-carrid key2 = wa-airpfrom )
INTO keys.
CLEAR members.
LOOP AT GROUP keys INTO member.
members = VALUE #( BASE members ( member ) ).
ENDLOOP.
out->write( members ).
out->write( |\n| ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `2e) Two column groups without members` ) ).
LOOP AT fli_tab INTO wa
GROUP BY ( key1 = wa-carrid key2 = wa-airpfrom
index = GROUP INDEX size = GROUP SIZE )
WITHOUT MEMBERS
INTO DATA(keysplus).
out->write( keysplus ).
out->write( |\n| ).
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_SQL_GROUP_BY</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: ABAP SQL - Grouping Internal Tables</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_STRING_PROC</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: String processing</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_STRUCTURES</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Structures</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,678 @@
***********************************************************************
*
* ABAP Cheat Sheet: ABAP Unit Tests
*
* -------------------------- PURPOSE ----------------------------------
* - Example to demonstrate ABAP unit tests.
* - Topics covered: Test classes and test methods, special methods,
* implementing and injecting test doubles (constructor injection,
* back door injection, test seams)
*
* ----------------------- RUN ABAP UNIT TEST---------------------------
* - Open the class with the ABAP development tools for Eclipse (ADT).
* - Choose Ctrl/Cmd + Shift + F10 to launch all tests in the class.
* You can also right-click somewhere in the class and choose
* Run as -> ABAP Unit Test.
* - The results of a test run are displayed in the ABAP Unit tab in ADT
* and can be evaluated. The Failure Trace section provides information
* on errors found.
* - If you are interested in test coverage, you can choose
* Ctrl/Cmd + Shift + F11, or make a right-click, choose Run as ->
* ABAP Unit Test With..., select the Coverage checkbox and choose
* Execute. You can then check the results in the ABAP Coverage tab,
* what code is tested and what not.
*
* ----------------------- RUN CLASS -----------------------------
* - Open the class with the ABAP development tools for Eclipse (ADT).
* - Choose F9 to run the class.
* - Check the console output.
* - To understand the context and the ABAP syntax used, check the notes
* included in the class as comments or refer to the respective topic
* in the ABAP Keyword Documentation.
* - Due to the amount of output in the console, the examples include
* numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example
* sections. Plus, the variable name is displayed in most cases. Hence,
* to easier and faster find the relevant output in the console, just
* search in the console for the number/variable name (CTRL + F in the
* console) or use the debugger.
*
* ----------------------------- NOTE -----------------------------------
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: Unit tests</p>
"! Example to demonstrate ABAP unit tests.<br>Choose F9 in ADT to run the class.
"! To run all unit tests of the class, choose Ctrl/Cmd + Shift + F10.
CLASS zcl_demo_abap_unit_test DEFINITION
PUBLIC
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES: if_oo_adt_classrun.
CLASS-METHODS: class_constructor.
"Optional parameter for the instance constructor for the purpose of
"constructor injection
METHODS constructor
IMPORTING iref_data_prov TYPE REF TO zdemo_abap_get_data_itf OPTIONAL.
PROTECTED SECTION.
TYPES carr_tab TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY.
METHODS: select_flight_data IMPORTING carrier TYPE zdemo_abap_fli-carrid
RETURNING VALUE(flight_data) TYPE carr_tab.
PRIVATE SECTION.
TYPES: int_tab_so TYPE SORTED TABLE OF i WITH UNIQUE KEY table_line,
int_tab_st TYPE STANDARD TABLE OF i WITH EMPTY KEY,
occ_rate TYPE p LENGTH 4 DECIMALS 2,
BEGIN OF nums_struc,
num1 TYPE i,
num2 TYPE i,
END OF nums_struc,
nums_tab TYPE TABLE OF nums_struc WITH EMPTY KEY.
DATA: seats_table TYPE zdemo_abap_get_data_itf=>carr_tab,
flight_tab TYPE TABLE OF zdemo_abap_fli,
"Reference variable for back door injection
"Note: In the example, it is a local interface declared in the
"Local Types tab (the CCIMP include). To make the type known to
"the global class, see the Class-relevant Local Types tab (the CCDEF include).
data_provider_local_itf TYPE REF TO lif_get_data,
"Reference variable for constructor injection
"In the example, the type refers to a global interface.
data_provider_global_itf TYPE REF TO zdemo_abap_get_data_itf,
"For demonstrating setter injection
data_provider_setter_inj TYPE REF TO zdemo_abap_get_data_itf,
"For demonstrating parameter injection
data_provider_param_inj TYPE REF TO zdemo_abap_get_data_itf..
METHODS:
"Calculates the sum of two numbers
"This method demonstrates the use of the setup and teardown methods in the test class.
get_sum IMPORTING key TYPE zdemo_abap_tab1-key_field
char TYPE zdemo_abap_tab1-char1
RETURNING VALUE(sum) TYPE i,
"Calculates the common divisors and the greatest common divisor of two numbers
get_common_div_and_gcd IMPORTING a TYPE i
b TYPE i
EXPORTING common_divisors TYPE int_tab_so
gcd TYPE i,
"Calculates the digit sum of a number
get_digit_sum IMPORTING num TYPE i
RETURNING VALUE(digit_sum) TYPE i,
"Multiple methods that all do the same (they calculate the occupancy rate of flights)
"but serve different demonstration purposes for the ABAP unit tests in the example.
"The method implementations involve a depended-on component (DOC). In this case,
"it is a database access.
"The methods are intentionally implemented in a similar way. Therefore, almost
"all of the following methods will display the same output in the console when the
"class is executed using F9.
"Method to demonstrate test double injection using inheritance and method redefinition
get_occ_rate_using_meth IMPORTING carrier_id TYPE zdemo_abap_fli-carrid
RETURNING VALUE(occupancy_rate) TYPE occ_rate,
"Method to demonstrate test double injection using test seams
get_occ_rate_test_seam IMPORTING carrier_id TYPE zdemo_abap_fli-carrid
EXPORTING occupancy_rate TYPE occ_rate
num1 TYPE i
num2 TYPE i,
"Method to demonstrate test double injection using back door injection and a local interface
get_occ_rate_local_itf IMPORTING carrier_id TYPE zdemo_abap_fli-carrid
RETURNING VALUE(occupancy_rate) TYPE occ_rate,
"Method to demonstrate test double injection using constructor injection and a global interface
get_occ_rate_global_itf IMPORTING carrier_id TYPE zdemo_abap_fli-carrid
RETURNING VALUE(occupancy_rate) TYPE occ_rate,
"Method to demonstrate test double injection using setter injection and a global interface
get_occ_rate_setter_inj IMPORTING carrier_id TYPE zdemo_abap_fli-carrid
RETURNING VALUE(occupancy_rate) TYPE occ_rate,
"Method for setter injection
setter_meth IMPORTING data_prov TYPE REF TO zdemo_abap_get_data_itf,
"Method to demonstrate test double injection using parameter injection and a global interface
"An optional parameter is specified for passing the test double if the method is tested.
get_occ_rate_param_inj IMPORTING carrier_id TYPE zdemo_abap_fli-carrid
data_prov TYPE REF TO zdemo_abap_get_data_itf OPTIONAL
RETURNING VALUE(occupancy_rate) TYPE occ_rate.
ENDCLASS.
CLASS zcl_demo_abap_unit_test IMPLEMENTATION.
METHOD class_constructor.
"Filling demo database tables.
zcl_demo_abap_aux=>fill_dbtabs( ).
"Preparing a demo database table for this example (get_sum method)
DELETE FROM zdemo_abap_tab1.
INSERT zdemo_abap_tab1 FROM @(
VALUE #( key_field = 1 char1 = 'aaa' char2 = 'bbb' num1 = 25 num2 = 75 ) ).
ENDMETHOD.
METHOD constructor.
"For demonstrating the back door injection
data_provider_local_itf = NEW lcl_data_prov_local_itf( ).
"For demonstrating the constructor injection
IF iref_data_prov IS BOUND.
"Note: The parameter is only bound when you run the unit test.
"When you run the unit test and you debug, you will see that iref_data_prov
"has a type reference to LTD_TEST_DATA_GLOBAL_INTF.
data_provider_global_itf = iref_data_prov.
ELSE.
data_provider_global_itf = NEW lcl_data_prov_glo_itf( ).
ENDIF.
"Object creation for the method call in the get_occ_rate_setter_inj method
data_provider_setter_inj = NEW lcl_data_prov_glo_itf( ).
ENDMETHOD.
METHOD get_common_div_and_gcd.
"Calculates the common divisors and the greatest common divisor of two numbers
CLEAR: common_divisors, gcd.
CHECK a >= 1.
CHECK b >= 1.
IF a >= b.
DATA(greater_num) = a.
DATA(lower_num) = b.
ELSE.
greater_num = b.
lower_num = a.
ENDIF.
"Getting common divisors
DATA(div) = 1.
WHILE div <= lower_num.
IF lower_num MOD div = 0.
DATA(divisor) = lower_num / div.
INSERT divisor INTO TABLE common_divisors.
ENDIF.
div += 1.
ENDWHILE.
LOOP AT common_divisors ASSIGNING FIELD-SYMBOL(<i>).
IF greater_num MOD <i> <> 0.
DELETE common_divisors WHERE table_line = <i>.
ENDIF.
ENDLOOP.
"Extracting the greatest common divisor from the list of common divisors
gcd = common_divisors[ lines( common_divisors ) ].
ENDMETHOD.
METHOD get_digit_sum.
"Calculates the digit sum of a number
CLEAR digit_sum.
CHECK num >= 0.
DATA(converted_int) = CONV string( num ).
DATA(len) = strlen( converted_int ).
DO len TIMES.
DATA(idx) = sy-index - 1.
digit_sum = digit_sum + converted_int+idx(1).
ENDDO.
ENDMETHOD.
METHOD get_occ_rate_global_itf.
"Method to demonstrate test double injection using constructor injection
"and a global interface
DATA total_seatsmax_global_itf TYPE i.
DATA total_seatsocc_global_itf TYPE i.
"Assumption: The original code in this method was as follows (the line commented out).
"It was identified as DOC (reading data from a database table).
"DATA(flight_data) = select_flight_data( carrier = carrier_id ).
"Instead of a method call like above and for a proper unit testing, a global interface
"is provided.
"In the example, an interface method is implemented in a local class in the local types
"tab (CCIMP include): lcl_data_prov_glo_itf
"When the class is executed using F9, the object used here refers to type lcl_data_prov_glo_itf.
"When the unit test is executed, the object used here refers to type ltd_test_data_global_intf,
"i.e. the local test double is injected.
DATA(flight_data) = data_provider_global_itf->select_flight_data( carrier = carrier_id ).
LOOP AT flight_data ASSIGNING FIELD-SYMBOL(<l>).
total_seatsmax_global_itf = total_seatsmax_global_itf + <l>-seatsmax.
total_seatsocc_global_itf = total_seatsocc_global_itf + <l>-seatsocc.
ENDLOOP.
occupancy_rate = total_seatsocc_global_itf / total_seatsmax_global_itf * 100.
ENDMETHOD.
METHOD get_occ_rate_local_itf.
"Method to demonstrate test double injection using back door
"injection and a local interface
DATA total_seatsmax_local_itf TYPE i.
DATA total_seatsocc_local_itf TYPE i.
"Assumption: The original code in this method was as follows (the line commented out).
"It was identified as DOC (reading data from a database table).
"DATA(flight_data) = select_flight_data( carrier = carrier_id ).
"Instead of a method call like above and for a proper unit testing - a global interface
"is not available - a local interface is created, and
"an interface method is implemented. In this example, the local interface is
"created in the local types tab (CCIMP include): lif_get_data
"A local class (lcl_data_prov_local_itf) is also created in the CCIMP include. It
"implements the local interface.
"When the class is executed using F9, the object used here refers to type lcl_data_prov_local_itf.
"When the unit test is executed, the object used here refers to type ltd_test_data_local_itf,
"i.e. the local test double is injected.
DATA(flight_data) = data_provider_local_itf->select_flight_data( carrier = carrier_id ).
LOOP AT flight_data ASSIGNING FIELD-SYMBOL(<k>).
total_seatsmax_local_itf = total_seatsmax_local_itf + <k>-seatsmax.
total_seatsocc_local_itf = total_seatsocc_local_itf + <k>-seatsocc.
ENDLOOP.
occupancy_rate = total_seatsocc_local_itf / total_seatsmax_local_itf * 100.
ENDMETHOD.
METHOD get_occ_rate_param_inj.
"This method demonstrates test double injection using parameter injection.
DATA total_seatsmax_param_inj TYPE i.
DATA total_seatsocc_param_inj TYPE i.
"Assumption: The original code in this method was as follows (the line commented out).
"It was identified as DOC (reading data from a database table).
"DATA(flight_data) = select_flight_data( carrier = carrier_id ).
"Instead of a method call like above and for a proper unit testing, a global interface
"is provided.
"In the example, an interface method is implemented in a local class in the local types
"tab (CCIMP include): lcl_data_prov_glo_itf
"The method has an optional importing parameter. When the unit test is executed,
"the parameter is bound. An object of the test double class is passed in that case.
"Otherwise, when the class is executed using F9, an object of the actual data provider
"is created.
IF data_prov IS BOUND.
data_provider_param_inj = data_prov.
ELSE.
data_provider_param_inj = NEW lcl_data_prov_glo_itf( ).
ENDIF.
DATA(flight_data) = data_provider_param_inj->select_flight_data( carrier = carrier_id ).
LOOP AT flight_data ASSIGNING FIELD-SYMBOL(<o>).
total_seatsmax_param_inj = total_seatsmax_param_inj + <o>-seatsmax.
total_seatsocc_param_inj = total_seatsocc_param_inj + <o>-seatsocc.
ENDLOOP.
occupancy_rate = total_seatsocc_param_inj / total_seatsmax_param_inj * 100.
ENDMETHOD.
METHOD get_occ_rate_setter_inj.
"This method demonstrates test double injection using setting injection.
"See the setter_meth method.
DATA total_seatsmax_setter_inj TYPE i.
DATA total_seatsocc_setter_inj TYPE i.
"Assumption: The original code in this method was as follows (the line commented out).
"It was identified as DOC (reading data from a database table).
"DATA(flight_data) = select_flight_data( carrier = carrier_id ).
"Instead of a method call like above and for a proper unit testing, a global interface
"is provided.
"In the example, an interface method is implemented in a local class in the local types
"tab (CCIMP include): lcl_data_prov_glo_itf
"See the comment in the setter_meth method
DATA(flight_data) = data_provider_setter_inj->select_flight_data( carrier = carrier_id ).
LOOP AT flight_data ASSIGNING FIELD-SYMBOL(<n>).
total_seatsmax_setter_inj = total_seatsmax_setter_inj + <n>-seatsmax.
total_seatsocc_setter_inj = total_seatsocc_setter_inj + <n>-seatsocc.
ENDLOOP.
occupancy_rate = total_seatsocc_setter_inj / total_seatsmax_setter_inj * 100.
ENDMETHOD.
METHOD get_occ_rate_test_seam.
"Method to demonstrate test double injection using test seams
"Note: The code is just for demonstration purposes. Of course, the result can be
"achieved more elegantly using SQL expressions, for example.
TEST-SEAM select_flights.
"DOC
SELECT seatsmax, seatsocc
FROM zdemo_abap_fli
WHERE carrid = @carrier_id
INTO CORRESPONDING FIELDS OF TABLE @seats_table.
END-TEST-SEAM.
DATA total_seatsmax_tm TYPE i.
DATA total_seatsocc_tm TYPE i.
LOOP AT seats_table ASSIGNING FIELD-SYMBOL(<j>).
total_seatsmax_tm = total_seatsmax_tm + <j>-seatsmax.
total_seatsocc_tm = total_seatsocc_tm + <j>-seatsocc.
ENDLOOP.
occupancy_rate = total_seatsocc_tm / total_seatsmax_tm * 100.
"Further examples for test seams
DATA(var) = 0.
"Empty test seam; code is injected during unit test
"Check the output when running the class using F9 and
"the test results when running the unit test.
TEST-SEAM num1.
END-TEST-SEAM.
IF var = 0.
num1 = 1.
ELSE.
num1 = 999.
ENDIF.
num2 = 0.
"Empty injection
"See the test class: The code that is included in the test
"seam should be excluded from the test. Therefore, the
"test injection block in the test class is empty.
"Check the output when running the class using F9 and
"the test results when running the unit test.
TEST-SEAM num2.
num2 = 123.
END-TEST-SEAM.
ENDMETHOD.
METHOD get_occ_rate_using_meth.
"This method demonstrates test double injection using inheritance and method redefinition.
DATA total_seatsmax_no TYPE i.
DATA total_seatsocc_no TYPE i.
"During the unit test, the redefined method in the test class is called.
DATA(flight_data) = select_flight_data( carrier = carrier_id ).
LOOP AT flight_data ASSIGNING FIELD-SYMBOL(<m>).
total_seatsmax_no = total_seatsmax_no + <m>-seatsmax.
total_seatsocc_no = total_seatsocc_no + <m>-seatsocc.
ENDLOOP.
occupancy_rate = total_seatsocc_no / total_seatsmax_no * 100.
ENDMETHOD.
METHOD get_sum.
"The method selects a record from a database table and sums the values
"of two fields, both are of type i.
SELECT SINGLE
FROM zdemo_abap_tab1
FIELDS num1 + num2 AS sum
WHERE key_field = @key
AND char1 = @char
INTO @sum.
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
"Note: The example includes a couple of implementations for the methods
"declared above. And by choosing F9 in ADT, you can run the class and check the
"output in the console.
"However, the focus of the example is unit tests. Therefore, check the
"test classes and methods in the test include (Test Classes tab in ADT).
"Choose Ctrl/Cmd + Shift + F10 to launch all tests in the class and check the
"test results in the ABAP Unit tab in ADT.
out->write( |ABAP Cheat Sheet Example: ABAP Unit Tests\n\n| ).
out->write( `************************************************************************` ).
out->write( `---> Choose Ctrl/Cmd + Shift + F10 to launch all tests in the class <---` ).
out->write( |************************************************************************\n| ).
out->write( |1) get_sum Method\n\n| ).
"This method demonstrates the use of the setup and teardown methods in the test class.
DATA(sum) = get_sum( key = 1 char = 'aaa' ).
out->write( data = sum name = `sum` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `2) get_common_div_and_gcd Method` ) ).
"Filling an internal table with numbers on whose bases the common divisors and the
"greatest common divisor are to be calculated
DATA(tab) = VALUE nums_tab( ( num1 = 10 num2 = 20 )
( num1 = 100 num2 = 200 )
( num1 = 12 num2 = 6 )
( num1 = 5 num2 = 1 )
( num1 = 50 num2 = 50 )
( num1 = 4 num2 = 8 ) ).
LOOP AT tab ASSIGNING FIELD-SYMBOL(<a>).
DATA(tabix) = sy-tabix.
get_common_div_and_gcd( EXPORTING a = <a>-num1
b = <a>-num2
IMPORTING common_divisors = DATA(common_divs) gcd = DATA(gcd) ).
out->write( |Common divisors of { <a>-num1 } and { <a>-num2 }\n| ).
out->write( |\n| ).
out->write( data = common_divs name = `common_divs` ).
out->write( |\n| ).
out->write( |Greatest common divisor of { <a>-num1 } and { <a>-num2 }: { gcd } | ).
out->write( |\n| ).
IF tabix < lines( tab ).
out->write( `--------------------------` ).
out->write( |\n| ).
ENDIF.
ENDLOOP.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `3) get_digit_sum Method` ) ).
"Filling an internal table with numbers on whose bases the digit sum is to be calculated
DATA(tab_i) = VALUE int_tab_so( ( 12 )
( 123 )
( 3 )
( 8246 )
( 1001001 )
( 0 ) ).
LOOP AT tab_i ASSIGNING FIELD-SYMBOL(<b>).
DATA(digit_sum) = get_digit_sum( <b> ).
out->write( |The digit sum of { <b> } is { digit_sum }.| ).
out->write( |\n| ).
ENDLOOP.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `4) get_occ_rate_using_meth Method` ) ).
"In the test class, this method demonstrates test double injection
"using inheritance and method redefinition.
"Filling an internal table with carrier ids on whose bases the occupancy
"rate is to be calculated.
DATA(tab_str) = VALUE zdemo_abap_get_data_itf=>carr_tab( ( carrid = 'LH' )
( carrid = 'AA' )
( carrid = 'DL' ) ).
LOOP AT tab_str ASSIGNING FIELD-SYMBOL(<c>).
DATA(occupancy_rate) = get_occ_rate_using_meth( <c>-carrid ).
out->write( |The occupancy rate for airline { <c>-carrid } is { occupancy_rate }%.| ).
out->write( |\n| ).
ENDLOOP.
out->write( zcl_demo_abap_aux=>heading( `5) get_occ_rate_test_seam Method` ) ).
"This method demonstrates test double injection using test seams.
LOOP AT tab_str ASSIGNING FIELD-SYMBOL(<d>).
get_occ_rate_test_seam( EXPORTING carrier_id = <d>-carrid
IMPORTING occupancy_rate = DATA(occupancy_rate_test_seam)
num1 = DATA(num1)
num2 = DATA(num2) ).
out->write( |The occupancy rate for airline { <d>-carrid } is { occupancy_rate_test_seam }%.| ).
out->write( |\n| ).
out->write( |num1: { num1 }| ).
out->write( |\n| ).
out->write( |num2: { num2 }| ).
out->write( |\n| ).
ENDLOOP.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `6) get_occ_rate_local_itf Method` ) ).
"This method demonstrates test double injection using back door
"injection and a local interface.
LOOP AT tab_str ASSIGNING FIELD-SYMBOL(<e>).
DATA(occupancy_rate_local_itf) = get_occ_rate_local_itf( <e>-carrid ).
out->write( |The occupancy rate for airline { <e>-carrid } is { occupancy_rate_local_itf }%.| ).
out->write( |\n| ).
ENDLOOP.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `7) get_occ_rate_global_itf Method` ) ).
"This method demonstrates test double injection using constructor
"injection and a global interface.
LOOP AT tab_str ASSIGNING FIELD-SYMBOL(<f>).
DATA(occupancy_rate_global_itf) = get_occ_rate_global_itf( <f>-carrid ).
out->write( |The occupancy rate for airline { <f>-carrid } is { occupancy_rate_global_itf }%.| ).
out->write( |\n| ).
ENDLOOP.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `8) get_occ_rate_setter_inj Method` ) ).
"This method demonstrates test double injection using setter injection and a global interface.
LOOP AT tab_str ASSIGNING FIELD-SYMBOL(<g>).
DATA(occupancy_rate_setter_inj) = get_occ_rate_setter_inj( <g>-carrid ).
out->write( |The occupancy rate for airline { <g>-carrid } is { occupancy_rate_setter_inj }%.| ).
out->write( |\n| ).
ENDLOOP.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `9) get_occ_rate_param_inj Method` ) ).
"This method demonstrates test double injection using parameter injection and a global interface.
LOOP AT tab_str ASSIGNING FIELD-SYMBOL(<h>).
DATA(occupancy_rate_param_inj) = get_occ_rate_param_inj( carrier_id = <h>-carrid ).
out->write( |The occupancy rate for airline { <h>-carrid } is { occupancy_rate_param_inj }%.| ).
out->write( |\n| ).
ENDLOOP.
ENDMETHOD.
METHOD select_flight_data.
"Method that is identified as DOC in the method implementations above.
"This method is also used for demonstrating test double injection and method redefinition.
SELECT seatsmax, seatsocc
FROM zdemo_abap_fli
WHERE carrid = @carrier
INTO CORRESPONDING FIELDS OF TABLE @flight_data.
ENDMETHOD.
METHOD setter_meth.
"Method to demonstrate the test double injection using setter injection
"When the unit test is executed, an object of the test double class is passed as
"a parameter. Then, the object used here refers to type ltd_test_data_setter_inj,
"i.e. the local test double is injected.
data_provider_setter_inj = data_prov.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,4 @@
*"* use this source file for any type of declarations (class
*"* definitions, interfaces or type declarations) you need for
*"* components in the private section
INTERFACE lif_get_data DEFERRED.

View File

@@ -0,0 +1,73 @@
******************************************************
* Local interface
******************************************************
INTERFACE lif_get_data.
TYPES: carr_tab TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY,
occ_rate TYPE p LENGTH 4 DECIMALS 2.
METHODS:
select_flight_data IMPORTING carrier TYPE zdemo_abap_fli-carrid
RETURNING VALUE(flight_data) TYPE carr_tab,
"This method is included to demonstrate the PARTIALLY IMPLEMENTED
"addition in the test class when implementing the test double
say_hello RETURNING VALUE(hi) TYPE string.
ENDINTERFACE.
******************************************************
* Local class
* The class implements the local interface.
******************************************************
CLASS lcl_data_prov_local_itf DEFINITION.
PUBLIC SECTION.
INTERFACES lif_get_data.
ENDCLASS.
CLASS lcl_data_prov_local_itf IMPLEMENTATION.
METHOD lif_get_data~select_flight_data.
SELECT seatsmax, seatsocc
FROM zdemo_abap_fli
WHERE carrid = @carrier
INTO CORRESPONDING FIELDS OF TABLE @flight_data.
ENDMETHOD.
METHOD lif_get_data~say_hello.
hi = `Hello, ` && sy-uname && `.`.
ENDMETHOD.
ENDCLASS.
******************************************************
* Local class that implements a global interface
* It serves the purpose of a data provider. It can be
* imagined as a global class, and a method that is
* implemented there and called by the class under test
* is identified as DOC. A local class is used in the
* example to keep the number of separate artifacts small.
******************************************************
CLASS lcl_data_prov_glo_itf DEFINITION.
PUBLIC SECTION.
INTERFACES zdemo_abap_get_data_itf.
ENDCLASS.
CLASS lcl_data_prov_glo_itf IMPLEMENTATION.
METHOD zdemo_abap_get_data_itf~select_flight_data.
SELECT seatsmax, seatsocc
FROM zdemo_abap_fli
WHERE carrid = @carrier
INTO CORRESPONDING FIELDS OF TABLE @flight_data.
ENDMETHOD.
METHOD zdemo_abap_get_data_itf~say_hello.
hi = `Hello, ` && sy-uname && `.`.
ENDMETHOD.
ENDCLASS.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_UNIT_TEST</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Unit tests</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_XML_JSON</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: Working with XML and JSON in ABAP</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,6 @@
@EndUserText.label: 'Demo abstract entity'
define abstract entity zdemo_abap_abstract_ent
{
col1: abap.char(25);
col2: abap.char(25);
}

View File

@@ -0,0 +1,17 @@
{
"BASEINFO":
{
"FROM":
[],
"ASSOCIATED":
[],
"BASE":
[],
"ANNO_REF":
[],
"SCALAR_FUNCTION":
[],
"VERSION":0,
"ANNOREF_EVALUATION_ERROR":""
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_ABSTRACT_ENT</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>Demo abstract entity</DDTEXT>
<SOURCE_TYPE>A</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_TABL" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DD02V>
<TABNAME>ZDEMO_ABAP_CARR</TABNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<TABCLASS>TRANSP</TABCLASS>
<CLIDEP>X</CLIDEP>
<DDTEXT>Demo table: Airline</DDTEXT>
<MASTERLANG>E</MASTERLANG>
<CONTFLAG>A</CONTFLAG>
<EXCLASS>1</EXCLASS>
</DD02V>
<DD09L>
<TABNAME>ZDEMO_ABAP_CARR</TABNAME>
<AS4LOCAL>A</AS4LOCAL>
<TABKAT>0</TABKAT>
<TABART>APPL0</TABART>
<BUFALLOW>N</BUFALLOW>
</DD09L>
<DD03P_TABLE>
<DD03P>
<FIELDNAME>MANDT</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CLNT</DATATYPE>
<LENG>000003</LENG>
<MASK> CLNT</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CARRID</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000003</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CARRNAME</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000040</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000020</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CURRCODE</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000010</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CUKY</DATATYPE>
<LENG>000005</LENG>
<MASK> CUKY</MASK>
</DD03P>
<DD03P>
<FIELDNAME>URL</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000510</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000255</LENG>
<MASK> CHAR</MASK>
</DD03P>
</DD03P_TABLE>
<TABL_EXTRAS>
<TDDAT>
<TABNAME>ZDEMO_ABAP_CARR</TABNAME>
<CCLASS>CUS_DEV_SUP_DA</CCLASS>
</TDDAT>
</TABL_EXTRAS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,9 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view entity ZDEMO_ABAP_CARR_VE
as select from zdemo_abap_carr
{
key carrid,
carrname,
currcode,
url
}

View File

@@ -0,0 +1,19 @@
{
"BASEINFO":
{
"FROM":
[
"ZDEMO_ABAP_CARR"
],
"ASSOCIATED":
[],
"BASE":
[],
"ANNO_REF":
[],
"SCALAR_FUNCTION":
[],
"VERSION":0,
"ANNOREF_EVALUATION_ERROR":""
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_CARR_VE</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>Demo CDS view entity</DDTEXT>
<SOURCE_TYPE>W</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,63 @@
// ABAP CDS cheat sheet example:
// Aggregate expressions in the element list of CDS view entities
//
//////////////////////////------ NOTES ------//////////////////////////////////
// - CDS view entity selects from a demo database table
// - Demonstrates various aggregate expressions in the element list
// - As a prerequisite, run the class zcl_demo_abap_cds_ve to populate the
// database tables of the example. Otherwise, no data is displayed.
//
//////////////////////------ DATA PREVIEW ------///////////////////////////////
// - Choose F8 in ADT to open the data preview and check out the data displayed
// - For comparing and checking the output, you can also open the data preview
// for the database table. In ADT, press and hold CTRL and click the database
// table name. In the opened table artifact, choose F8 to open the data preview.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS view entity: Aggregate expressions'
define view entity zdemo_abap_cds_ve_agg_exp
as select from zdemo_abap_fli
{
// The element list intentionally includes few fields only to focus on the effect of aggregate expressions.
key carrid,
currency,
// -------- Aggregate expressions --------
// - Aggregate expressions can be used as elements of an element list. Other positions are possible.
// - An alias name must be specified.
// - A GROUP BY clause is required. It must list all non-aggregated fields from the element list.
// - Additions: If ALL is used, all rows in the result set are respected. This is the default setting.
// If DISTINCT is used, only distinct values of an argument are respected.
// - Note: There may or may not be spaces between the parentheses following avg, min, etc., and the
// content specified within.
// AVG (Returns the average value of an argument)
avg( seatsocc as abap.dec(15,2)) as avg_seats_occ,
avg( cast(paymentsum as abap.dec(15, 2)) as abap.dec(15,2)) as avg_paysum,
// SUM (Returns the sum of an argument)
// Since a currency field is used in the example, an annotatin is required.
@Semantics.amount.currencyCode: 'currency'
sum(paymentsum) as total_paysum,
// MIN (Returns the least value of an argument)
min( seatsocc ) as min_occ_seats,
// MAX (Returns the greatest value of an argument)
max( seatsocc ) as max_occ_seats,
max( all seatsocc ) as max_occ_seats_all, //Same result as above, ALL is optional
// COUNT (Returns counted lines)
count(*) as cnt, // * means that all lines are respected
count(distinct planetype) as cnt_planetype //DISTINCT means that the number of dinstinct values if an argument is counted;
//e.g. if 3 is returned, it means there are 3 different plane types among the result set
}
//GROUP BY clause that lists all non-aggregated fields from the element list
group by
carrid,
currency

View File

@@ -0,0 +1,19 @@
{
"BASEINFO":
{
"FROM":
[
"ZDEMO_ABAP_FLI"
],
"ASSOCIATED":
[],
"BASE":
[],
"ANNO_REF":
[],
"SCALAR_FUNCTION":
[],
"VERSION":0,
"ANNOREF_EVALUATION_ERROR":""
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_CDS_VE_AGG_EXP</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>CDS view entity: Aggregate expressions</DDTEXT>
<SOURCE_TYPE>W</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,144 @@
// ABAP CDS cheat sheet example: Associations
//
//////////////////////////------ NOTES ------//////////////////////////////////
// - CDS view entity that selects from a demo CDS view entity and demonstrates
// associations. A selection of use cases of associations is covered. For
// more information and examples, see the ABAP Keyword Documentation.
// - As a prerequisite, run the class zcl_demo_abap_cds_ve to populate the
// database tables of the example. Otherwise, no data is displayed.
// - For further notes on associations, see the commented out information further
// down.
// - To see how the joins are realized on the database, you can right-click anywhere
// in the source code and choose 'Show SQL Create Statement'. The example
// includes associations where only left outer joins are performed.
//
//////////////////////------ DATA PREVIEW ------///////////////////////////////
// - Choose F8 in ADT to open the data preview and check out the data displayed
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS view entity: Associations 1'
define view entity zdemo_abap_cds_ve_assoc
// In this example, the data source, from which data is read, is another CDS view entity.
// This source CDS view entity selects all fields from the demo database table zdemo_abap_flsch.
// It also contains exposed associations that are used here.
as select from zdemo_abap_cds_ve_assoc_e as _flsch
// 1) One use case of assocations, which is not covered here, can be the use in the FROM clause.
// - That is, you can use an association as data source by specifying a path expression.
// - For example, the CDS view entity zdemo_abap_cds_ve_assoc_e exposes an association
// _carr_exp. Therefore, a FROM clause as follows is possible:
// ... as select from zdemo_abap_cds_ve_assoc_e._carr_exp as _flsch ...
// 2) Adding fields of an association target to the element list (of the same CDS view entity)
// - In this case, since data is requested, a join is carried out.
// - The data preview (choose F8) shows the values for the added fields.
// - In this example, the association is used, but not exposed. Therefore, it cannot be used
// in path expressions in other CDS entities as shown in 3).
association [1..1] to zdemo_abap_carr as _carr1 on _flsch.Carrid = _carr1.carrid
association [1..1] to zdemo_abap_carr as _carr2 on _flsch.Carrid = _carr2.carrid
association [1..*] to zdemo_abap_fli as _fli on _flsch.Carrid = _fli.carrid
// 3) Exposing associations
// - In this example, no fields of the association target are added to the element list.
// But the assocation is exposed in the element list. Therefore, it can be used
// in path expressions in other CDS entities.
// - In this case, since data is not requested, a join is not carried out. It is up to
// to the consumer (e.g. an ABAP SQL statement or other CDS view entities) to request
// fields (one field, multiple fields, all fields ...). Only then, a join is performed.
// - The data preview (choose F8) does not show any data of the association target.
// - Compare the ON condition to the ones above. For demonstration purposes, the carrid
// field is specified with an alias name in the element list. To refer to this name,
// the prefix $projection. is required. As above, you can also use the original name.
association [1..1] to zdemo_abap_carr as _carr3 on $projection.carrier = _carr3.carrid
{
// Including fields from the data source
// The prefix _flsch. is actually not necessary here in the example. It's intentionally included to emphasize the data source.
key _flsch.Carrid as carrier,
key _flsch.Connid as connection_id,
_flsch.Cityfrom,
_flsch.Cityto,
// Regarding 2) Adding fields of an association target to the element list
// - Two fields are added in the element list.
// - You can make a right-click and choose 'Show SQL Create Statement' to check how the join is performed.
// - Because a left outer join is performed, the coalesce function is included for a field.
// If there are null values, the specified character literal is inserted.
// - Only these two fields are respected from the association target.
_carr1.carrname as carrier_name,
coalesce(_carr1.url, 'NULL') as carr_url,
// Regarding 3) Exposing associations
// - The association is exposed in the element list (but no fields of the association target).
// - As demonstrated in the executable class of this cheat sheet, an ABAP SQL statement
// can request data of the association target.
// - The data preview does not include any fields from the association target. Likewise,
// the 'SQL Create Statement' does not show any join with this assocation.
_carr3,
// 4) Using associations that are exposed in external views
// - The CDS view entity that is used as data source in the SELECT list exposes
// associations.
// - Such an association is used in a path expression here to include a field from the
// association target in the element list. In this case, this CDS view entity is
// a consumer of the association. A join is performed, as can be seen in the
// 'SQL Create Statement' view.
_flsch._carr_exp.currcode as curr_exposed,
// 5) Attributes of path expression
// - Attributes are specified in angle brackets after each CDS association to define
// further properties. These can be the cardinality, join type that is implemented when used,
// and filter conditions
// Speciying filter conditions and the join type
// - Only if a join type is specified explicitly, the addition WHERE must be specified
// - The example specifies the join type. Therefore, WHERE is required. Here in the example,
// the specification can also be the one commented out below because it implicitly has
// the same effect. Here, a left outer join is performed by default.
// - The operand specified on the left side of the condition must be a field of the association target.
_carr2[left outer where $projection.carrier = 'LH'].url as fcond_url,
//_carr2[$projection.carrier = 'LH'].url as fcond_url
// Specifying the cardinality of the current CDS association
// - The values 1: (current CDS association is declared as unique) and *: (non-unique) are possible.
// - You can use 1: to prevent a syntax warning in case of a path specified with filter conditions, for example.
// - In the example, an association is specified with to many (there can be multiple flights for a flight route).
// Without the cardinality specification 1:, a warning would be displayed ("The association _fli can modify
// the cardinality of the results set").
// - Similar to the example above, the first line commented out below is also possible in this example.
// The second line commented out results in a syntax warning because it does not specify the
// cardinality 1:.
_fli[1:$projection.connection_id = connid].fldate as fcond_fldate
//_fli[1:left outer where $projection.connection_id = connid].fldate as fcond_fldate
//_fli[$projection.connection_id = connid].fldate as fcond_fldate
}
////////////////////////// --------- Notes on associations --------- /////////////////////////////////////////
// - They offer an advanced modelling capability for CDS data models. They define relationships between
// CDS entities (association source and target). On the database, associations are internally transformed into joins.
// - Compared to regular joins, associations differ in the following respects:
// - Joins are only performed on demand, i.e. when data is requested from the assocation by a consumer, e.g.
// using another CDS view entity or an ABAP SQL statement. In the regular joins (e.g. inner, outer joins), the
// join is always performed. When a CDS association is instantiated as join on the database, the association
// source represents the left side and the association target represents the right side of the join.
// - In the SELECT list, specifying the data source as a prefix is mandatory for all fields of the association.
// For joins, it is mandatory only for for non-unique names.
// - Unlike regular joins, associations can be reused in different positions and basically replace very complex
// join expressions.
// - Use of associations:
// - Including fields from the association target in the current view
// - Exposing associations so that they can be used in other CDS entities or in ABAP SQL
// - Associations can be used in path expressions (a sequence of associations) at different operand positions.
// - Associations can be specified with additional semantic information, such as cardinality.
// - Specifying the (optional) cardinality is a means of documenting the semantics of the data model.
// - Cardinality is specified in square brackets [ ]. Minimum and maximum can be specified, for example
// one to one [1..1], one to many [1..*]. The default is [0..1]. Specifying the minimum value is optional (the
// default value is 0), i.e. [0..1] is [1], [0..*] is [*]. The minimum cannot be *, the maximum not 0.
// - Maximum values greater than 1 can lead to syntax errors or warnings. Generally, a non-matching cardinality
// usually produces a warning.
// - If the cardinality is not specified, it is to one by default [x..1].
// - Compositions and to-parent associations are special kinds of CDS associations. See the ABAP Keyword Documentation.

View File

@@ -0,0 +1,23 @@
{
"BASEINFO":
{
"FROM":
[
"ZDEMO_ABAP_CDS_VE_ASSOC_E",
"ZDEMO_ABAP_CARR",
"ZDEMO_ABAP_FLI"
],
"ASSOCIATED":
[
"ZDEMO_ABAP_CARR"
],
"BASE":
[],
"ANNO_REF":
[],
"SCALAR_FUNCTION":
[],
"VERSION":0,
"ANNOREF_EVALUATION_ERROR":""
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_CDS_VE_ASSOC</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>CDS view entity: Associations</DDTEXT>
<SOURCE_TYPE>W</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,40 @@
// ABAP CDS cheat sheet example: Associations
//
//////////////////////////------ NOTES ------//////////////////////////////////
// - CDS view entity that selects from a demo database table.
// - The purpose of this CDS view entity is to demonstrate associations. The view
// is used as a data source in another CDS view entity.
// - As a prerequisite, run the class zcl_demo_abap_cds_ve to populate the
// database tables of the example. Otherwise, no data is displayed.
//
//////////////////////------ DATA PREVIEW ------///////////////////////////////
// - Choose F8 in ADT to open the data preview and check out the data displayed
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS view entity: Associations'
define view entity zdemo_abap_cds_ve_assoc_e
as select from zdemo_abap_flsch as _flsch
association [1..1] to zdemo_abap_carr as _carr_exp on _flsch.carrid = _carr_exp.carrid
association [1..*] to zdemo_abap_fli as _fli on _flsch.carrid = _fli.carrid and _flsch.connid = _fli.connid
{
key _flsch.carrid as Carrid,
key _flsch.connid as Connid,
_flsch.countryfr as Countryfr,
_flsch.cityfrom as Cityfrom,
_flsch.airpfrom as Airpfrom,
_flsch.countryto as Countryto,
_flsch.cityto as Cityto,
_flsch.airpto as Airpto,
_flsch.fltime as Fltime,
_flsch.deptime as Deptime,
_flsch.arrtime as Arrtime,
_flsch.distance as Distance,
_flsch.distid as Distid,
_flsch.fltype as Fltype,
_flsch.period as Period,
_carr_exp,
_fli
}

View File

@@ -0,0 +1,22 @@
{
"BASEINFO":
{
"FROM":
[
"ZDEMO_ABAP_FLSCH"
],
"ASSOCIATED":
[
"ZDEMO_ABAP_CARR",
"ZDEMO_ABAP_FLI"
],
"BASE":
[],
"ANNO_REF":
[],
"SCALAR_FUNCTION":
[],
"VERSION":0,
"ANNOREF_EVALUATION_ERROR":""
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_CDS_VE_ASSOC_E</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>CDS view entity: Associations</DDTEXT>
<SOURCE_TYPE>W</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,132 @@
// ABAP CDS cheat sheet example: Joins
//
//////////////////////////------ NOTES ------//////////////////////////////////
// - CDS view entity selects from a demo database table
// - Demonstrates various joins
// - As a prerequisite, run the class zcl_demo_abap_cds_ve to populate the
// database tables of the example. Otherwise, no data is displayed.
// It is particularly needed in this case because it contains entries to
// visualize the effect of outer joins.
// - HOW TO:
// - To reduce the number of separate artifacts, this example CDS view entity
// contains the code for multiple joins, which is commented out.
// - To test out various joins, you can comment out and comment in the
// respective code sections (select the lines and choose CTRL + 7).
// - The example for inner joins is commented in by default. The relevant
// code sections are marked with "COMMENT IN/OUT ... START" and
// "COMMENT IN/OUT ... END" in both SELECT and element list
// (inner joins -> 1a / 1b). To test the left outer joins, for example,
// comment out the respective sections of the inner join and comment in
// the sections for left outer joins (2a, 2b), and so on.
// - Once done, activate the view and choose F8 to open the data preview.
// You must activate the view and choose F8 again for every change here
// because the alias names are different.
//
//////////////////////------ DATA PREVIEW ------///////////////////////////////
// - Choose F8 in ADT to open the data preview and check out the data displayed
// - Note the hints above regarding commenting in/out of code.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS view entity: Joins'
define view entity zdemo_abap_cds_ve_joins
as select from zdemo_abap_carr as _carr
// Notes on joins:
// - Joins combine two data sources into one result set, consisting of columns of both data sources
// - Rows of the result set are determined by the join type and by join conditions between columns of the data sources
// - Joins can be nested
// - Inner or outer join must contain a join condition after ON
// - Each element of the SELECT list must have the name of its data source as prefix
// - When joins are used, a WHERE condition affects the result set
// - The cardinality can be specified for left outer joins. For more details, see the ABAP Keyword Documentation.
/////////////////// ----- Example for INNER JOIN ----- /////////////////////////////////
// Notes:
// - Joins all entries of the data sources whose fields match the ON condition
// - In the table zdemo_abap_carr, there are entries in carrid that are not present in zdemo_abap_flsch.
// The same is true the other way round. The result only contains those entries that exist in both data sources
// based on the ON condition.
//// ----> COMMENT IN/OUT 1a START <-----
inner join zdemo_abap_flsch as _flsch_in on _carr.carrid = _flsch_in.carrid
//// ----> COMMENT IN/OUT 1a END <-----
//Alternative syntax: Specifying 'inner' is optional
// join zdemo_abap_flsch
// as _flsch_in on _carr.carrid = _flsch_in.carrid
/////////////////// ----- Example for LEFT OUTER JOIN ----- /////////////////////////////////
// Notes:
// - The join selects all entries on the left side. Entries that match the ON condition have the same content as in the inner join.
// In entries that do not match the ON condition, the elements on the right side have the null value.
// - To demonstrate the effect, the table zdemo_abap_carr contains entries for carrid that are not present in zdemo_abap_flsch.
// - Example in the element list:
// - The coalesce function can be used to prevent null values in the result set.
// - In the example, the function is used for an element to prevent null values.
//// ----> COMMENT IN/OUT 2A START <-----
// left outer join zdemo_abap_flsch as _flsch_lo on _carr.carrid = _flsch_lo.carrid
//// ----> COMMENT IN/OUT 2A END <-----
/////////////////// ----- Example for RIGHT OUTER JOIN ----- /////////////////////////////////
// Notes:
// - The join selects all entries on the right side. Entries that match the ON condition have the same content as in the inner join.
// In entries that do not match the ON condition, the elements on the left side have the null value.
// - To demonstrate the effect, the table zdemo_abap_carr contains entries for carrid that are not present in zdemo_abap_flsch.
// - Example in the element list:
// - Instead of the coalesce function, you can also use a CASE expression using a logical expression with IS [NOT] NULL
// to prevent null values in the result set.
// - In the example, a CASE expression is used for an element to prevent null values.
//// ----> COMMENT IN/OUT 3A START <-----
// right outer join zdemo_abap_flsch as _flsch_ro on _carr.carrid = _flsch_ro.carrid
//// ----> COMMENT IN/OUT 3A END <-----
/////////////////// ----- Example for CROSS JOIN ----- /////////////////////////////////
// Notes:
// - All entries on the left side are combined with all entries on the right side.
// - It is not possible to specify an ON condition.
//- The number of lines of the result is the number of left lines multiplied by the number of lines of the right table.
//// ----> COMMENT IN/OUT 4A START <-----
// cross join zdemo_abap_flsch as _flsch_cr
//// ----> COMMENT IN/OUT 4A END <-----
{
key _carr.carrid,
_carr.carrname,
/////////////////// ----- Example for INNER JOIN ----- /////////////////////////////////
// ----> COMMENT IN/OUT 1b START <-----
_flsch_in.cityfrom as cityfr_in,
_flsch_in.cityto as cityto_in
// ----> COMMENT IN/OUT 1b END <-----
/////////////////// ----- Example for LEFT OUTER JOIN ----- /////////////////////////////////
//// ----> COMMENT IN/OUT 2b START <-----
// _flsch_lo.cityfrom as cityfr_lo,
// coalesce(_flsch_lo.cityto, '???') as cityto_lo
//// ----> COMMENT IN/OUT 2b END <-----
/////////////////// ----- Example for RIGHT OUTER JOIN ----- /////////////////////////////////
//// ----> COMMENT IN/OUT 3b START <-----
// case when _carr.url is not null then _carr.url
// else '!!!'
// end as url_ro,
// _flsch_ro.cityfrom as cityfr_ro,
// _flsch_ro.cityto as cityto_ro
//// ----> COMMENT IN/OUT 3b END <-----
/////////////////// ----- Example for CROSS JOIN ----- /////////////////////////////////
//// ----> COMMENT IN/OUT 4b START <-----
// _flsch_cr.cityfrom as cityfr_cr,
// _flsch_cr.cityto as cityto_cr
//// ----> COMMENT IN/OUT 4b END <-----
}

View File

@@ -0,0 +1,20 @@
{
"BASEINFO":
{
"FROM":
[
"ZDEMO_ABAP_CARR",
"ZDEMO_ABAP_FLSCH"
],
"ASSOCIATED":
[],
"BASE":
[],
"ANNO_REF":
[],
"SCALAR_FUNCTION":
[],
"VERSION":0,
"ANNOREF_EVALUATION_ERROR":""
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_CDS_VE_JOINS</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>CDS view entity: Joins</DDTEXT>
<SOURCE_TYPE>W</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,237 @@
// ABAP CDS cheat sheet example:
// Operands and expressions in CDS view entities
//
//////////////////////////------ NOTES ------//////////////////////////////////
// - CDS view entity selects from a demo database table
// - Demonstrates various syntax options regarding operands and expressions
// - As a prerequisite, run the class zcl_demo_abap_cds_ve to populate the
// database tables of the example. Otherwise, no data is displayed.
//
//////////////////////------ DATA PREVIEW ------///////////////////////////////
// - Choose F8 in ADT to open the data preview and check out the data displayed
// - The example includes parameters. Therefore, you are prompted to insert a
// value. In this example, the parameter (maximum seats in a plane) is used for
// the WHERE clause (the lower the number entered, the more entries in the result
// set).
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////------ Annotations ------///////////////////////////////
// Annotations add metadata to a CDS object that expands the syntax options of SQL.
// There's a predefined set of SAP annotations. Their specification is optional.
// Example for a view entity annotation (only possible in CDS view entities)
// The following annotation defines implicit access control when ABAP SQL is used
// to access the CDS view entity. Here, it is determined that no access control
// is required.
@AccessControl.authorizationCheck: #NOT_REQUIRED
// Example for an entity annotation (annotations that can be used in all CDS entities)
// The following annotation provides a translatable short text of the CDS entity.
@EndUserText.label: 'CDS view entity: Operands/Expressions'
define view entity zdemo_abap_cds_ve_sel
with parameters
p_smax : abap.int4 //Input parameter typed with an elementary data type;
//can also be a DDIC data element
as select from zdemo_abap_fli //Selection from a demo database table;
//an alias name can be also specified ... as _fli, for example
// The following element list demonstrates possible elements, operands and expressions.
// Note: Many of the operands and expressions demonstrated below can occur in multiple positions.
// Refer to the ABAP Keyword Documentation for the details.
{
// -------- Specifying fields of the data source --------
//- Multiple fields of the data source from which to be selected are specified.
//- Field names can be prefixed with the name of the data source (or, if specified, with the alias name).
//- Alias names can be specified for the elements. Note: In case of joins (selection from multiple sources)
// all elements must be prefixed with the name of the data source. See the view entity demonstrating joins.
//- KEY defines the current element as a key element; must be placed at the beginning; in CDS entities the key
// elements are mainly used to document the semantics of the data model (Note: They do not define unique lines
// in its result with regard to the key.)
key carrid as CarrierId, //Alias name specified
key zdemo_abap_fli.connid as Connid, //Element prefixed with data source; alias name specified
key fldate,
price,
currency,
paymentsum,
planetype,
seatsmax,
seatsocc,
// -------- Literals --------
// Typed literals (cover most built-in types of the ABAP Dictionary)
// As is true for all of the following elements, an alias name must be specified.
abap.int4'12345' as int4, //Typed numeric literal
abap.char'hallo' as c5, //Typed character literal
abap.dats'20240101' as date_lit, //Date
// Note: In case of a currency or quantity field specified with a typed literal, a reference
// to a currency key or unit is mandatory, which requires an annotation. The currency example
// here uses the following annotation. The element 'currency' from above is referenced.
@Semantics.amount.currencyCode: 'currency'
abap.curr'12.34' as curr,
abap.dec'0.9' as discnt,
abap.unit'KM' as kilometers,
// Untyped literals
'Minutes' as fltime_ut, //Untyped character literal
1 as num_lit, //Untyped numeric literal
// -------- Parameters --------
// Parameters can be specified in an operand position.
// The name of the parameter must be prefixed by $parameters.
$parameters.p_smax as param,
// -------- Session variables --------
// Among other sesion variables, there are built-in session variables available.
$session.user as usr,
$session.client as clnt,
$session.system_language as langu,
$session.system_date as sys_date,
$session.user_timezone as usr_time,
$session.user_date as usr_date,
// -------- Expressions --------
//Note: Aggregate and path expressions are covered in a separate CDS view entity.
// -------- Cast expressions --------
// Convert the value of operands to a specified type after as
// The examples use built-in data types only.
// Note: Regarding which conversion combinations of types are possible, see the ABAP Keyword Documentation.
// There are special conversion rules for every combination.
cast( price as abap.dec(15,2) ) as cast_curr2dec,
// The following example uses the prefix $projection. which defines reuse expressions.
// That is, you can refer to an element defined previously in the element list of the same CDS view entity.
// Note that this is only possible in dedicated positions. One of them is a cast expression.
cast( $projection.date_lit as abap.char(8) ) as cast_dats2c,
// -------- Arithmetic expressions --------
seatsocc_b + seatsocc_f as occ_seats_classes,
seatsmax - seatsocc as free_seats,
2 * 2 as mult,
9 / 3 as div,
//Arithmetic expressions using cast and reuse expressions
cast( paymentsum as abap.dec(17,2) ) * abap.dec'0.75' as discount_1,
$projection.cast_curr2dec * $projection.discnt as discount_2,
cast( seatsocc / seatsmax * 100 as abap.dec(10, 2) ) as occupancy_rate,
// -------- Case expressions --------
// Simple case distinction for comparing values of operands with other operands.
// The first operand specified after THEN for which the comparison is true is
// returned as a result. No match: Result is determined by the ELSE branch.
case currency
when 'EUR' then 'X'
when 'USD' then 'Y'
else 'Z'
end as case1,
// You can use the ELSE NULL addition that returns the null value.
// Note: If ELSE is not specified, the null value is returned as a result.
case $projection.case1
when 'X' then 'A'
else null
end as case2,
// Complex case distinction (searched case) for evaluating conditions
case
when seatsmax <= 150 then 'small'
when seatsmax > 150 and seatsmax < 300 then 'middle'
when seatsmax >= 300 then 'large'
else '?'
end as case3,
// -------- Excursion: Logical expressions --------
// The following nonsense example using a CASE expression just visualizes the rich variety of options.
//Comparison operators
// Boolean operators AND, OR, NOT as well as parenthesized expressions are possible.
case
when seatsmax = 385 and not ( seatsocc > 380 and seatsocc <> 379 or seatsocc <= 120 or paymentsum >= 200000 ) then 'A'
//Interval comparisons
when seatsmax between 250 and 350 and seatsocc not between 1 and 100 then 'B'
//Pattern comparisons ('%' -> wildcard character, represents any character string, '_' -> stands for any character)
when carrid like '_L' then 'C'
//Checking for null and initial value
when currency is not null or carrid is not initial then 'D'
else '?'
end as case4,
// -------- Built-in functions --------
// SQL functions (only a selection is covered here)
// Numeric functions
// The example uses typed and untyped literals only as arguments.
abs( abap.int4'-1' ) as nf_abs,
ceil( abap.decfloat34'3.333' ) as nf_ceil,
floor( abap.decfloat34'3.333' ) as nf_floor,
div( 25, 5 ) as nf_div,
mod( 11, 3 ) as nf_mod,
division( 1, 3, 2 ) as nf_division,
round( abap.decfloat34'1.337', 2 ) as nf_round,
// String functions
concat(planetype, '-#') as sf_concat,
concat_with_space(carrid, '#', 1) as sf_conc_ws, //3rd argument: number of spaces
instr(currency, 'U') as sf_instr, //Position of the first occurrence of the string from the substring in the argument (case-sensitive)
left(currency, 2) as sf_left, //String of length n starting from the left of an expression
length(planetype) as sf_len, //Number of characters in an argument ignoring trailing blanks
lower(carrid) as sf_lower, //String with a length of an argument in which all uppercase letters are transformed to lowercase letters
lpad(carrid, 5, '#') as sf_lpad, //String of a length with the right-aligned content of an argument without trailing blanks and in which leading blanks produced by the expanded string are replaced by the characters from an argument (respecting all blanks)
ltrim(planetype, 'A') as sf_ltrim, //String with the content of an argument in which all trailing blanks and leading characters are removed that match the specified character.
replace(currency, 'U', '#') as sf_repl, //String in which all instances of the second argument are replaced by the content from the third argument
replace_regexpr(PCRE => '\\d', //More optional parameters are possible; the example replaces all digits
VALUE => planetype,
WITH => '#',
RESULT_LENGTH => 10) as sf_repl_regex,
right(currency, 2) as sf_right, //String of length n starting from the right of an expression
rpad(carrid, 5, '#') as sf_rpad, //See lpad; here, right-algined content
rtrim(planetype, '0') as sf_rtrim, //See ltrim; here, from the right
substring(planetype, 4, 3) as sf_sub, //Returns a substring; second argument: position from where to start; third argument: length of the extracted substring
upper( 'abap' ) as sf_upper, //Transforms to upper case
// Coalesce function
// Checks whether the argument contains a null value. If it contains it, it returns the value of the second argument
// Otherwise, it returns the value of the first argument.
// This example has no null values in carrid, therefore the carrid value is output. See the example view about joins.
coalesce(carrid, 'N') as coalesced,
// Special functions
// Type conversion functions
fltp_to_dec( abap.fltp'12.34' as abap.dec(10,1) ) as fltp2dec,
// Unit conversion
// In the following example, the number that is input as parameter is used as the value for a distance in miles. It is converted to kilometers.
@Semantics.quantity.unitOfMeasure: 'kilometers'
unit_conversion( quantity => $parameters.p_smax,
source_unit => abap.unit'MI',
target_unit => $projection.kilometers ) as converted_value,
// Date/Time functions
// The function in the example calculates the days between to dates. The actual parameters must have the built-in data type DATS.
dats_days_between(fldate,$projection.date_lit) as days_bw1,
// The following example is similar to the example above. Here, the function expects the type DATN.
// It also shows the use of another function (dats_to_datn) that converts the types.
// Note: Only literals can be passed to the final two parameters on_error, on_initial.
datn_days_between(dats_to_datn(fldate,'INITIAL','INITIAL') , dats_to_datn($session.user_date,'INITIAL','INITIAL')) as days_bw2,
// The following function adds days to a date. Here, the date a week from today is calculated.
dats_add_days($session.user_date,7,'INITIAL') as in1week,
// Time stamp functions
// Getting the current time stamp
utcl_current() as ts,
// Adding seconds to a time stamp
utcl_add_seconds($projection.ts,60) as in1minute
}
// -------- Clauses for the SELECT statement --------
// SELECT statements of a CDS view entitiy can be specified with optional clauses
// Among them, there are WHERE (to restrict the rows of the result set), GROUP BY (grouping the result set(
// HAVING (further restriction after the GROUP BY clause) clauses and other set operators like EXCEPT, INTERSECT and UNION.
// This example uses a simple WHERE clause. It uses a condition that includes the input parameter to restrict the result set.
where seatsmax > $parameters.p_smax

View File

@@ -0,0 +1,19 @@
{
"BASEINFO":
{
"FROM":
[
"ZDEMO_ABAP_FLI"
],
"ASSOCIATED":
[],
"BASE":
[],
"ANNO_REF":
[],
"SCALAR_FUNCTION":
[],
"VERSION":0,
"ANNOREF_EVALUATION_ERROR":""
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_CDS_VE_SEL</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>CDS view entity: Operands and expressions</DDTEXT>
<SOURCE_TYPE>W</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_TABL" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DD02V>
<TABNAME>ZDEMO_ABAP_DRAFT</TABNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<TABCLASS>TRANSP</TABCLASS>
<CLIDEP>X</CLIDEP>
<LANGDEP>X</LANGDEP>
<DDTEXT>Draft table for RAP calculator</DDTEXT>
<MASTERLANG>E</MASTERLANG>
<MAINFLAG>X</MAINFLAG>
<CONTFLAG>A</CONTFLAG>
<EXCLASS>1</EXCLASS>
</DD02V>
<DD09L>
<TABNAME>ZDEMO_ABAP_DRAFT</TABNAME>
<AS4LOCAL>A</AS4LOCAL>
<TABKAT>0</TABKAT>
<TABART>APPL0</TABART>
<BUFALLOW>N</BUFALLOW>
</DD09L>
<DD03P_TABLE>
<DD03P>
<FIELDNAME>CLIENT</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CLNT</DATATYPE>
<LENG>000003</LENG>
<MASK> CLNT</MASK>
</DD03P>
<DD03P>
<FIELDNAME>ID</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ROLLNAME>SYSUUID_X16</ROLLNAME>
<ADMINFIELD>0</ADMINFIELD>
<NOTNULL>X</NOTNULL>
<COMPTYPE>E</COMPTYPE>
</DD03P>
<DD03P>
<FIELDNAME>DRAFTUUID</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ROLLNAME>SYSUUID_X16</ROLLNAME>
<ADMINFIELD>0</ADMINFIELD>
<NOTNULL>X</NOTNULL>
<COMPTYPE>E</COMPTYPE>
</DD03P>
<DD03P>
<FIELDNAME>NUM1</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
<DD03P>
<FIELDNAME>ARITHM_OP</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000002</INTLEN>
<DATATYPE>CHAR</DATATYPE>
<LENG>000001</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>NUM2</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CALC_RESULT</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>g</INTTYPE>
<INTLEN>000008</INTLEN>
<DATATYPE>STRG</DATATYPE>
<MASK> STRG</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CREA_DATE_TIME</FIELDNAME>
<ROLLNAME>TIMESTAMPL</ROLLNAME>
<ADMINFIELD>0</ADMINFIELD>
<COMPTYPE>E</COMPTYPE>
</DD03P>
<DD03P>
<FIELDNAME>LCHG_DATE_TIME</FIELDNAME>
<ROLLNAME>TIMESTAMPL</ROLLNAME>
<ADMINFIELD>0</ADMINFIELD>
<COMPTYPE>E</COMPTYPE>
</DD03P>
<DD03P>
<FIELDNAME>.INCLUDE</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<PRECFIELD>SYCH_BDL_DRAFT_ADMIN_INC</PRECFIELD>
<MASK> S</MASK>
<DDTEXT>Standard Include for Draft Administration (BDL Syntax Check)</DDTEXT>
<COMPTYPE>S</COMPTYPE>
<GROUPNAME>%ADMIN</GROUPNAME>
</DD03P>
</DD03P_TABLE>
<TABL_EXTRAS>
<TDDAT>
<TABNAME>ZDEMO_ABAP_DRAFT</TABNAME>
<CCLASS>CUS_DEV_SUP_DA</CCLASS>
</TDDAT>
</TABL_EXTRAS>
</asx:values>
</asx:abap>
</abapGit>

182
src/zdemo_abap_fli.tabl.xml Normal file
View File

@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_TABL" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DD02V>
<TABNAME>ZDEMO_ABAP_FLI</TABNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<TABCLASS>TRANSP</TABCLASS>
<CLIDEP>X</CLIDEP>
<DDTEXT>Demo table: Flight</DDTEXT>
<MASTERLANG>E</MASTERLANG>
<CONTFLAG>A</CONTFLAG>
<EXCLASS>1</EXCLASS>
</DD02V>
<DD09L>
<TABNAME>ZDEMO_ABAP_FLI</TABNAME>
<AS4LOCAL>A</AS4LOCAL>
<TABKAT>0</TABKAT>
<TABART>APPL0</TABART>
<BUFALLOW>N</BUFALLOW>
</DD09L>
<DD03P_TABLE>
<DD03P>
<FIELDNAME>MANDT</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CLNT</DATATYPE>
<LENG>000003</LENG>
<MASK> CLNT</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CARRID</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000003</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CONNID</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>N</INTTYPE>
<INTLEN>000008</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>NUMC</DATATYPE>
<LENG>000004</LENG>
<MASK> NUMC</MASK>
</DD03P>
<DD03P>
<FIELDNAME>FLDATE</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>D</INTTYPE>
<INTLEN>000016</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>DATS</DATATYPE>
<LENG>000008</LENG>
<MASK> DATS</MASK>
<SHLPORIGIN>T</SHLPORIGIN>
</DD03P>
<DD03P>
<FIELDNAME>PRICE</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>P</INTTYPE>
<INTLEN>000008</INTLEN>
<REFTABLE>ZDEMO_ABAP_FLI</REFTABLE>
<REFFIELD>CURRENCY</REFFIELD>
<DATATYPE>CURR</DATATYPE>
<LENG>000015</LENG>
<DECIMALS>000002</DECIMALS>
<MASK> CURR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CURRENCY</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000010</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CUKY</DATATYPE>
<LENG>000005</LENG>
<MASK> CUKY</MASK>
</DD03P>
<DD03P>
<FIELDNAME>PLANETYPE</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000020</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000010</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>SEATSMAX</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
<DD03P>
<FIELDNAME>SEATSOCC</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
<DD03P>
<FIELDNAME>PAYMENTSUM</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>P</INTTYPE>
<INTLEN>000009</INTLEN>
<REFTABLE>ZDEMO_ABAP_FLI</REFTABLE>
<REFFIELD>CURRENCY</REFFIELD>
<NOTNULL>X</NOTNULL>
<DATATYPE>CURR</DATATYPE>
<LENG>000017</LENG>
<DECIMALS>000002</DECIMALS>
<MASK> CURR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>SEATSMAX_B</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
<DD03P>
<FIELDNAME>SEATSOCC_B</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
<DD03P>
<FIELDNAME>SEATSMAX_F</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
<DD03P>
<FIELDNAME>SEATSOCC_F</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
</DD03P_TABLE>
<TABL_EXTRAS>
<TDDAT>
<TABNAME>ZDEMO_ABAP_FLI</TABNAME>
<CCLASS>CUS_DEV_SUP_DA</CCLASS>
</TDDAT>
</TABL_EXTRAS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,18 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view entity ZDEMO_ABAP_FLI_VE
as select from zdemo_abap_fli
{
key carrid,
key connid,
key fldate,
price,
currency,
planetype,
seatsmax,
seatsocc,
paymentsum,
seatsmax_b,
seatsocc_b,
seatsmax_f,
seatsocc_f
}

View File

@@ -0,0 +1,19 @@
{
"BASEINFO":
{
"FROM":
[
"ZDEMO_ABAP_FLI"
],
"ASSOCIATED":
[],
"BASE":
[],
"ANNO_REF":
[],
"SCALAR_FUNCTION":
[],
"VERSION":0,
"ANNOREF_EVALUATION_ERROR":""
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_FLI_VE</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>Demo CDS view entity</DDTEXT>
<SOURCE_TYPE>W</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,199 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_TABL" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DD02V>
<TABNAME>ZDEMO_ABAP_FLSCH</TABNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<TABCLASS>TRANSP</TABCLASS>
<CLIDEP>X</CLIDEP>
<DDTEXT>Demo table: Flight schedule</DDTEXT>
<MASTERLANG>E</MASTERLANG>
<MAINFLAG>X</MAINFLAG>
<CONTFLAG>A</CONTFLAG>
<EXCLASS>1</EXCLASS>
</DD02V>
<DD09L>
<TABNAME>ZDEMO_ABAP_FLSCH</TABNAME>
<AS4LOCAL>A</AS4LOCAL>
<TABKAT>0</TABKAT>
<TABART>APPL0</TABART>
<BUFALLOW>N</BUFALLOW>
</DD09L>
<DD03P_TABLE>
<DD03P>
<FIELDNAME>MANDT</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CLNT</DATATYPE>
<LENG>000003</LENG>
<MASK> CLNT</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CARRID</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000003</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CONNID</FIELDNAME>
<KEYFLAG>X</KEYFLAG>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>N</INTTYPE>
<INTLEN>000008</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>NUMC</DATATYPE>
<LENG>000004</LENG>
<MASK> NUMC</MASK>
</DD03P>
<DD03P>
<FIELDNAME>COUNTRYFR</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<DATATYPE>CHAR</DATATYPE>
<LENG>000003</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CITYFROM</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000040</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000020</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>AIRPFROM</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000003</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>COUNTRYTO</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<DATATYPE>CHAR</DATATYPE>
<LENG>000003</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>CITYTO</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000040</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000020</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>AIRPTO</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000003</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>FLTIME</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
</DD03P>
<DD03P>
<FIELDNAME>DEPTIME</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>T</INTTYPE>
<INTLEN>000012</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>TIMS</DATATYPE>
<LENG>000006</LENG>
<MASK> TIMS</MASK>
<SHLPORIGIN>T</SHLPORIGIN>
</DD03P>
<DD03P>
<FIELDNAME>ARRTIME</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>T</INTTYPE>
<INTLEN>000012</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>TIMS</DATATYPE>
<LENG>000006</LENG>
<MASK> TIMS</MASK>
<SHLPORIGIN>T</SHLPORIGIN>
</DD03P>
<DD03P>
<FIELDNAME>DISTANCE</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>P</INTTYPE>
<INTLEN>000005</INTLEN>
<REFTABLE>ZDEMO_ABAP_FLSCH</REFTABLE>
<REFFIELD>DISTID</REFFIELD>
<NOTNULL>X</NOTNULL>
<DATATYPE>QUAN</DATATYPE>
<LENG>000009</LENG>
<DECIMALS>000004</DECIMALS>
<MASK> QUAN</MASK>
</DD03P>
<DD03P>
<FIELDNAME>DISTID</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000006</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>UNIT</DATATYPE>
<LENG>000003</LENG>
<MASK> UNIT</MASK>
</DD03P>
<DD03P>
<FIELDNAME>FLTYPE</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>C</INTTYPE>
<INTLEN>000002</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>CHAR</DATATYPE>
<LENG>000001</LENG>
<MASK> CHAR</MASK>
</DD03P>
<DD03P>
<FIELDNAME>PERIOD</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000001</INTLEN>
<NOTNULL>X</NOTNULL>
<DATATYPE>INT1</DATATYPE>
<LENG>000003</LENG>
<MASK> INT1</MASK>
</DD03P>
</DD03P_TABLE>
<TABL_EXTRAS>
<TDDAT>
<TABNAME>ZDEMO_ABAP_FLSCH</TABNAME>
<CCLASS>CUS_DEV_SUP_DA</CCLASS>
</TDDAT>
</TABL_EXTRAS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -0,0 +1,20 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view entity ZDEMO_ABAP_FLSCH_VE
as select from zdemo_abap_flsch
{
key carrid,
key connid,
countryfr,
cityfrom,
airpfrom,
countryto,
cityto,
airpto,
fltime,
deptime,
arrtime,
distance,
distid,
fltype,
period
}

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