This commit is contained in:
danrega
2024-08-07 17:11:47 +02:00
parent bf887f71ed
commit abbeebbe2f
8 changed files with 467 additions and 45 deletions

View File

@@ -1025,7 +1025,7 @@ CLASS zcl_some_class IMPLEMENTATION.
"******* DEEP addition / EXPANDING NESTED TABLES addition *******
"Handling deep components such as nested internal tables
"Creating an populating demo internal tables
"Creating and populating demo internal tables
TYPES: BEGIN OF st_d,
char_a TYPE c LENGTH 2,
char_b TYPE c LENGTH 2,
@@ -1642,7 +1642,7 @@ ENDCLASS.
### Example: Exploring READ TABLE Statements and Table Expressions
Expand the following collapsible section to view the code of an example. To try it out, create a demo class named `zcl_some_class` and paste the code into it. After activation, choose *F9* in ADT to execute the class.
The example is not set up to display output in the console. You may want to set a break point at the first position possible and walk through the example in the debugger. You may want to set a breakpoint at the earliest possible position and walk through the example in the debugger. This will allow you to double-click on data objects and observe how the different statements affect their contents.
The example is not set up to display output in the console. You may want to set a break point at the first position possible and walk through the example in the debugger. This will allow you to double-click on data objects and observe how the different statements affect their contents.
<details>
<summary>Expand to view the code</summary>

View File

@@ -392,7 +392,7 @@ ENDIF.
<td>
- Cannot be used with the addition `SINGLE`.
- See more information here [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_clause.htm).
- See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_clause.htm).
<br>

View File

@@ -16,7 +16,7 @@
- [Parameter Interface](#parameter-interface)
- [Constructors](#constructors)
- [Working with Objects and Components](#working-with-objects-and-components)
- [Declaring Reference Variables](#declaring-reference-variables)
- [Declaring Object Reference Variables](#declaring-object-reference-variables)
- [Creating Objects](#creating-objects)
- [Working with Reference Variables](#working-with-reference-variables)
- [Accessing Attributes](#accessing-attributes)
@@ -35,6 +35,7 @@
- [Interface Reference Variables and Accessing Objects](#interface-reference-variables-and-accessing-objects)
- [Excursions](#excursions)
- [Friendship](#friendship)
- [Friendship between Global and Local Classes](#friendship-between-global-and-local-classes)
- [Events](#events)
- [Examples for Design Patterns: Factory Methods and Singletons](#examples-for-design-patterns-factory-methods-and-singletons)
- [More Information](#more-information)
@@ -660,13 +661,12 @@ ENDCLASS.
## Working with Objects and Components
### Declaring Reference Variables
- To create an object, a [reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_variable_glosry.htm "Glossary Entry")
must be declared.
- Such an [object reference
variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_refer_variable_glosry.htm "Glossary Entry")
is also necessary for accessing objects and their components. That means objects are not directly accessed but only via references that point to
those objects. This object reference variable contains the reference to the object - after assigning the reference to the object (see further down).
### Declaring Object Reference Variables
- To create an object, an [object reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_refer_variable_glosry.htm "Glossary Entry") must be declared.
- It is also necessary for accessing objects and their components. That means objects are not directly accessed but only via references that point to
those objects.
- This object reference variable contains the reference to the object - after assigning the reference to the object (see further down).
``` abap
"Declaring object reference variables
DATA: ref1 TYPE REF TO local_class,
@@ -2172,6 +2172,82 @@ CLASS global_class DEFINITION CREATE PUBLIC FRIENDS other_global_class ... .
<p align="right"><a href="#top">⬆️ back to top</a></p>
#### Friendship between Global and Local Classes
The following example demonstrates granting friendship between a global class and a local class (in the CCIMP include, *Local Types* tab in ADT). In the example, friendship is granted in both ways so that the global class can access private components of the local class, and the local class can access private components of the global class.
For more information, see the following topics:
- [`LOCAL FRIENDS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_local_friends.htm),
- [`DEFERRED`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_deferred.htm)
**Global class**
- Create a new global class (the example uses the name `zcl_some_class`) and copy and paste the following code in the *Global Class* tab in ADT.
- The class has a type and method declaration in the private section. They are used in the local class.
- Once activated (and the code of the other includes has been inserted), you can choose *F9* in ADT to run the class.
- When running the class, a method of the local class that is declared in the private section there is called. As a result of this method call, a string is assigned to an attribute that is also declared in the private section of the local class. This attribute is accessed by the global class, and finally displayed in the ADT console.
```abap
CLASS zcl_some_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
TYPES str TYPE string.
CLASS-METHODS get_hello RETURNING VALUE(hello) TYPE string.
ENDCLASS.
CLASS zcl_some_class IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
local_class=>say_hello( ).
DATA(hello) = local_class=>hello.
out->write( hello ).
ENDMETHOD.
METHOD get_hello.
hello = `Hello`.
ENDMETHOD.
ENDCLASS.
```
**CCDEF include (*Class-relevant Local Types* tab in ADT)**
- Regarding the includes, see the information in section [Excursion: Class Pool and Include Programs](#excursion-class-pool-and-include-programs)
- The LOCAL FRIENDS addition makes the local class a friend of the global class. The private components of the global class can then be accessed by the local class.
```abap
CLASS local_class DEFINITION DEFERRED.
CLASS zcl_some_class DEFINITION LOCAL FRIENDS local_class.
```
**CCIMP include (*Local Types* tab in ADT)**
- The FRIENDS addition makes the global class a friend of the local class. The private components of the local class can then be accessed by the global class.
- A type declared in the private section of the global class is used to type an attribute.
- The method, which is also declared in the private section, includes a method call in the implementation. It is a method delcared in the private section of the global class.
```abap
CLASS local_class DEFINITION FRIENDS zcl_some_class.
PUBLIC SECTION.
PROTECTED SECTION.
PRIVATE SECTION.
CLASS-DATA hello TYPE zcl_some_class=>str.
CLASS-METHODS say_hello.
ENDCLASS.
CLASS local_class IMPLEMENTATION.
METHOD say_hello.
hello = |{ zcl_some_class=>get_hello( ) } { sy-uname }.|.
ENDMETHOD.
ENDCLASS.
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
### Events
- [Events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenevent_glosry.htm "Glossary Entry")

View File

@@ -14,7 +14,7 @@
- [Declaring Data Reference Variables](#declaring-data-reference-variables)
- [Assigning References to Existing Data Objects](#assigning-references-to-existing-data-objects)
- [Creating New Data Objects at Runtime (Anonymous Data Objects)](#creating-new-data-objects-at-runtime-anonymous-data-objects)
- [Excursion: Creating Objects as Instances of Classes and CREATE OBJECT Statements](#excursion-creating-objects-as-instances-of-classes-and-create-object-statements)
- [Excursion with Object Reference Variables: Creating Objects as Instances of Classes and CREATE OBJECT Statements](#excursion-with-object-reference-variables-creating-objects-as-instances-of-classes-and-create-object-statements)
- [Assignments Between Two Reference Variables (Static and Dynamic Type, Upcast and Downcast)](#assignments-between-two-reference-variables-static-and-dynamic-type-upcast-and-downcast)
- [Addressing Data References](#addressing-data-references)
- [Excursion: Generic Data References and Field Symbols](#excursion-generic-data-references-and-field-symbols)
@@ -31,6 +31,7 @@
- [Validating Input for Dynamic Specifications (CL\_ABAP\_DYN\_PRG)](#validating-input-for-dynamic-specifications-cl_abap_dyn_prg)
- [Runtime Type Services (RTTS)](#runtime-type-services-rtts)
- [Getting Type Information at Runtime](#getting-type-information-at-runtime)
- [RTTI Method Calls](#rtti-method-calls)
- [Example: Exploring the RTTI Type Hierarchy](#example-exploring-the-rtti-type-hierarchy)
- [Excursion: Inline Declaration, CAST Operator, Method Chaining](#excursion-inline-declaration-cast-operator-method-chaining)
- [Absolute Names](#absolute-names)
@@ -573,7 +574,7 @@ SELECT SINGLE *
<p align="right"><a href="#top">⬆️ back to top</a></p>
#### Excursion: Creating Objects as Instances of Classes and CREATE OBJECT Statements
#### Excursion with Object Reference Variables: Creating Objects as Instances of Classes and CREATE OBJECT Statements
- To create an object, a [reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_variable_glosry.htm "Glossary Entry")
must be declared.
@@ -2389,6 +2390,184 @@ The type properties are represented by attributes that are accessible through th
> - For each type category (elementary type, table, and so on), there is a type description class (e.g. `CL_ABAP_STRUCTDESCR` for structures, as shown in the hierarchy tree above) that has special attributes (i.e. the properties of the respective types).
> - References to type description objects can be used, for example, after the `TYPE HANDLE` addition of the `CREATE DATA` and `ASSIGN` statements.
#### RTTI Method Calls
The following code example demonstrates a range of RTTI method calls. It includes retrieving type information at runtime for elementary and enumerated types, structures, internal tables, data references, classes, and interfaces. Find more information in the section below.
To try the example out, create a demo class named `zcl_some_class` and paste the code into it.
The example is not set up to display output in the console. So, after activation, you may want to set a break point at the first position possible and choose *F9* in ADT to execute the class. You can then walk through the example in the debugger. This will allow you to double-click on the variables and check out the contents. The example is similar to the one below, however, this only focuses on the method calls without output preparation among others.
```abap
CLASS zcl_some_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_some_class IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
"------------------------------------- Elementary types/data objects -------------------------------------
TYPES elem_type_ts TYPE timestampl.
DATA ts TYPE elem_type_ts VALUE '20240101081317.81011'.
DATA(tdo_a) = cl_abap_typedescr=>describe_by_data( ts ).
"DATA(tdo_a) = cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE_TS' ).
"Cast to get more specific information
DATA(tdo_elem) = CAST cl_abap_elemdescr( cl_abap_typedescr=>describe_by_data( ts ) ).
"DATA(tdo_elem) = CAST cl_abap_elemdescr( tdo_a ).
DATA(type_category_elem) = tdo_elem->kind.
DATA(type_kind_elem) = tdo_elem->type_kind.
DATA(decimals_elem) = tdo_elem->decimals.
DATA(output_length_elem) = tdo_elem->output_length.
DATA(absolute_name_elem) = tdo_elem->absolute_name.
DATA(relative_name_elem) = tdo_elem->get_relative_name( ).
DATA(is_ddic_type_elem) = tdo_elem->is_ddic_type( ).
DATA(applies_to_data_elem) = tdo_elem->applies_to_data( CONV timestamp( '20240808112458' ) ).
DATA(applies_to_dataref_elem) = tdo_elem->applies_to_data_ref( REF #( '20240808112458' ) ).
"Enumerated type
TYPES: BEGIN OF ENUM enum_t,
enum1,
enum2,
END OF ENUM enum_t.
DATA(dobj_enum) = enum2.
DATA(other_enum) = enum1.
DATA(tdo_enum) = CAST cl_abap_enumdescr( cl_abap_typedescr=>describe_by_data( enum2 ) ).
"DATA(tdo_enum) = CAST cl_abap_enumdescr( cl_abap_typedescr=>describe_by_name( 'ENUM_T' ) ).
DATA(type_category_enum) = tdo_enum->kind.
DATA(relative_name_enum) = tdo_enum->get_relative_name( ).
... "Explore more options by positioning the cursor behind -> and choosing CTRL + Space
DATA(base_kind_enum) = tdo_enum->base_type_kind.
DATA(members_enum) = tdo_enum->members.
DATA(applies_to_data_enum) = tdo_enum->applies_to_data( other_enum ).
"------------------------------------- Structure -------------------------------------
TYPES: BEGIN OF demo_struc_type,
comp1 TYPE c LENGTH 3,
comp2 TYPE i,
comp3 TYPE string,
END OF demo_struc_type.
DATA demo_struc TYPE demo_struc_type.
DATA(tdo_c) = cl_abap_typedescr=>describe_by_data( demo_struc ).
"DATA(tdo_c) = cl_abap_typedescr=>describe_by_name( 'DEMO_STRUC_TYPE' ).
"Cast to get more specific information
DATA(tdo_struc) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_data( demo_struc ) ).
"DATA(tdo_struc) = CAST cl_abap_structdescr( tdo_c ).
DATA(type_category_struc) = tdo_struc->kind.
DATA(relative_name_struc) = tdo_struc->get_relative_name( ).
... "Explore more options by positioning the cursor behind -> and choosing CTRL + Space
DATA(type_of_struc) = tdo_struc->struct_kind.
DATA(struc_comps) = tdo_struc->components.
DATA(struc_comps_more_details) = tdo_struc->get_components( ).
DATA(struc_has_include) = tdo_struc->has_include.
DATA(struc_incl_view) = tdo_struc->get_included_view( ).
DATA(applies_to_data_struc) = tdo_enum->applies_to_data( `some string` ).
"------------------------------------- Internal table -------------------------------------
TYPES tab_type TYPE SORTED TABLE OF demo_struc_type
WITH UNIQUE KEY comp1
WITH NON-UNIQUE SORTED KEY sec_key ALIAS sk COMPONENTS comp2 comp3.
DATA itab TYPE tab_type.
DATA(tdo_d) = cl_abap_typedescr=>describe_by_data( itab ).
"DATA(tdo_d) = cl_abap_typedescr=>describe_by_name( 'TAB_TYPE' ).
"Cast to get more specific information
DATA(tdo_itab) = CAST cl_abap_tabledescr( cl_abap_typedescr=>describe_by_data( itab ) ).
"DATA(tdo_itab) = CAST cl_abap_tabledescr( tdo_d ).
DATA(type_category_itab) = tdo_itab->kind.
DATA(relative_name_itab) = tdo_itab->get_relative_name( ).
... "Explore more options by positioning the cursor behind -> and choosing CTRL + Space
DATA(table_kind_itab) = tdo_itab->table_kind.
DATA(table_keys_itab) = tdo_itab->key.
DATA(table_keys_more_details_itab) = tdo_itab->get_keys( ).
DATA(table_has_unique_key_itab) = tdo_itab->has_unique_key.
DATA(table_key_alias_itab) = tdo_itab->get_key_aliases( ).
DATA(line_type_itab) = tdo_itab->get_table_line_type( ).
DATA(table_component_info_itab) = CAST cl_abap_structdescr( tdo_itab->get_table_line_type( ) ).
DATA(table_components_itab) = CAST cl_abap_structdescr( tdo_itab->get_table_line_type( ) )->components.
DATA(table_comps_more_info_itab) = CAST cl_abap_structdescr( tdo_itab->get_table_line_type( ) )->get_components( ).
DATA(applies_to_data_itab) = tdo_itab->applies_to_data( VALUE tab_type( ) ).
"------------------------------------- Data reference -------------------------------------
TYPES dref_type TYPE REF TO i.
DATA dref TYPE dref_type.
dref = NEW #( 1 ).
DATA(dref_b) = REF #( 2 ).
DATA(tdo_e) = cl_abap_typedescr=>describe_by_data( dref ).
"DATA(tdo_e) = cl_abap_typedescr=>describe_by_name( 'DREF_TYPE' ).
DATA(tdo_dref) = CAST cl_abap_refdescr( cl_abap_typedescr=>describe_by_data( dref ) ).
DATA(referenced_type_dref) = tdo_dref->get_referenced_type( ).
... "Explore more options by positioning the cursor behind -> and choosing CTRL + Space
"Using the describe_by_data_ref method
DATA(tdo_dref_b) = cl_abap_typedescr=>describe_by_data_ref( dref ).
"------------------------------------- Class -------------------------------------
"Creating an object reference variable
DATA(oref) = NEW cl_abap_dyn_prg( ).
"Using the describe_by_object_ref method
DATA(tdo_f) = cl_abap_typedescr=>describe_by_object_ref( oref ).
"DATA(tdo_f) = cl_abap_typedescr=>describe_by_name( 'CL_ABAP_DYN_PRG' ).
"Cast using cl_abap_classdescr to get class descriptions
DATA(tdo_cl) = CAST cl_abap_classdescr( cl_abap_typedescr=>describe_by_object_ref( oref ) ).
"DATA(tdo_cl) = CAST cl_abap_classdescr( tdo_f ).
DATA(class_kind_cl) = tdo_cl->class_kind.
DATA(attributes_cl) = tdo_cl->attributes.
DATA(interfaces_cl) = tdo_cl->interfaces.
DATA(events_cl) = tdo_cl->events.
DATA(methods_cl) = tdo_cl->methods.
DATA(super_class_cl) = tdo_cl->get_super_class_type( ).
DATA(super_class_name_cl) = super_class_cl->absolute_name.
DATA(is_instantiable_cl) = tdo_cl->is_instantiatable( ).
... "Explore more options by positioning the cursor behind -> and choosing CTRL + Space
"------------------------------------- Interface -------------------------------------
"This example only uses the describe_by_name method
DATA(tdo_g) = cl_abap_typedescr=>describe_by_name( 'IF_OO_ADT_CLASSRUN' ).
DATA(tdo_intf) = CAST cl_abap_intfdescr( cl_abap_typedescr=>describe_by_name( 'IF_OO_ADT_CLASSRUN' ) ).
"DATA(tdo_intf) = CAST cl_abap_classdescr( tdo_g ).
DATA(attributes_intf) = tdo_intf->attributes.
DATA(methods_intf) = tdo_intf->methods.
... "Explore more options by positioning the cursor behind -> and choosing CTRL + Space
ENDMETHOD.
ENDCLASS.
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
#### Example: Exploring the RTTI Type Hierarchy
The following example explores the RTTI type hierarchy and demonstrates how to retrieve various pieces of type information using RTTI attributes and methods. You can create a demo class (adapt the class name if needed), copy and paste the code, run the class with F9 in ADT, and check the output in the console.
@@ -2991,7 +3170,7 @@ CLASS zcl_some_class IMPLEMENTATION.
"Interface methods
"You can check the following table in the debugger. There is plenty of information available
"such as parameters, visibility , abstract/final, static/instance, and more.
"such as parameters, visibility, abstract/final, static/instance, and more.
"The example only writes the methods names to the string table.
DATA(intf_methods) = intf->methods.
INSERT |{ tabix } Methods: { REDUCE string( INIT str = `` FOR <methintf> IN intf_methods NEXT str = |{ str }| &&

View File

@@ -38,6 +38,7 @@
- [Searching Using Regular Expressions](#searching-using-regular-expressions)
- [System Classes for Regular Expressions](#system-classes-for-regular-expressions)
- [Replacing Using Regular Expressions](#replacing-using-regular-expressions)
- [Misc Examples Using Regular Expressions](#misc-examples-using-regular-expressions)
- [More String Functions](#more-string-functions)
- [Checking the Similarity of Strings](#checking-the-similarity-of-strings)
- [Repeating Strings](#repeating-strings)
@@ -1634,8 +1635,7 @@ IF s1 NP `i+`. ... "true; sy-fdpos = 11 (length of searched string)
#### Excursion: Common Regular Expressions
There are several ways to perform complex searches in strings using PCRE expressions. They can be quite complex. The following overview shows common PCRE expressions with simple examples.
For more information, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenregex_pcre_syntax_specials.htm).
There are several ways to perform complex searches in strings using PCRE expressions. They can be quite complex. The following overview shows common PCRE expressions with simple examples. It is not comprehensive. For more details, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenregex_pcre_syntax_specials.htm).
Characters and character types
@@ -1684,19 +1684,6 @@ Character Sets, Ranges, Subgroups and Lookarounds
> - Subgroups are useful in replacements. By using an expression with `$` and a number, such as `$1`, you can refer to a specific group. For example, you have a string `abcde`. A PCRE expression might be
`(ab|xy)c(d.)`, where two subgroups are specified within two pairs of parentheses. In a replacement pattern, you can refer to the first group with `$1` and the second group with `$2`. Thus, the replacement pattern `$2Z$1` results in `deZab`.
> - `(?:x)` creates a group but it is not captured. Example regular expression: `(?:ab)(ap)`. Example string: 'abap'. It matches 'abap', but `$1` will only contain 'ap'.
> - Note that `.` does not include new line feeds among others. If you want to capture a new line, you can use `\n` as regular expression. The following example string includes a new line. All content between the HTML p tags should be replaced. You could use a regular expression to capture any character or new line as follows:
> ```abap
> DATA(str_a) = |<p>Hallo\n</p><p>Ciao!</p><p>Salut.</p>|.
> DATA(str_b) = str_a.
>
> REPLACE ALL OCCURRENCES OF PCRE `(<p>)(.*?)(<\/p>)` IN str_a WITH `$1Hi$3`.
> "<p>Hallo
> "</p><p>Hi</p><p>Hi</p>
>
> "Regular expression: any character or a new line with zero or more repretitions
> REPLACE ALL OCCURRENCES OF PCRE `(<p>)(.|\n)*?(<\/p>)` IN str_b WITH `$1Hi$3`.
> "<p>Hi</p><p>Hi</p><p>Hi</p>
> ```
> - Regarding special characters, check the [Special Characters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenregex_pcre_syntax_specials.htm) topic in the ABAP Keyword Documentation. For example, a non-breaking space whose hex code is *U+00A0*. You can replace all of the non-breaking space occurrences in a string as follows:
> ```abap
> REPLACE ALL OCCURRENCES OF PCRE `\x{00A0}` IN some_string WITH ``.
@@ -1708,8 +1695,8 @@ Anchors and Positions
| Expression | Represents | Example Regex | Example String | Matches | Does not Match |
|---|---|---|---|---|---|
| `^` | Start of line, alternative: `\A` | `^.` or `\A.` | abc def | <ins>**a**</ins>bc def | abc <ins>**d**</ins>ef |
| `$` | End of line, alternative: `\Z` | `.$` or `.\Z` | abc def | abc de<ins>**f**</ins> | <ins>**a**</ins>bc def |
| `^` | Start of line | `^.` | abc def | <ins>**a**</ins>bc def | abc <ins>**d**</ins>ef |
| `$` | End of line | `.$` | abc def | abc de<ins>**f**</ins> | <ins>**a**</ins>bc def |
| `\b` | Start or end of word | 1. `\ba.` <br>2. `\Dd\b` <br>3. `\b.d\b` | abcd a12d ed | 1. <ins>**ab**</ins>cd <ins>**a1**</ins>2d ed <br>2. ab<ins>**cd**</ins> a12d <ins>**ed**</ins> <br> 3. abcd a12d <ins>**ed**</ins> | 1. ab<ins>**cd**</ins> a1<ins>**2d**</ins> ed <br> 2. abcd a1<ins>**2d**</ins> ed <br> 3. <ins>**abcd**</ins> <ins>**a12d**</ins> ed |
| `\B` | Negation of `\b`, not at the start or end of words | `\Be\B` | see an elefant | s<ins>**e**</ins>e an el<ins>**e**</ins>fant | s<ins>**ee**</ins> an <ins>**e**</ins>lefant |
@@ -1907,6 +1894,152 @@ REPLACE ALL OCCURRENCES OF PCRE `p.` IN s1 WITH `XY` "XY?aXY#ab?a
<p align="right"><a href="#top">⬆️ back to top</a></p>
#### Misc Examples Using Regular Expressions
This section demonstrates various examples using regular expressions. For example, it includes the handling of special characters.
Regarding special characters, check the [Special Characters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenregex_pcre_syntax_specials.htm) topic in the ABAP Keyword Documentation.
```abap
"String created with string template and control characters for
"new line, tab, and return
DATA(a) = |A B\nC\tD\rE|.
"Copies for more examples
DATA(b) = a.
DATA(c) = a.
"Replacing any whitespace character
REPLACE ALL OCCURRENCES OF PCRE `\s` IN a WITH `#`.
*A#B#C#D#E
"Replacing any character that is not a whitespace character
REPLACE ALL OCCURRENCES OF PCRE `\S` IN b WITH `#`.
*# #
*# #
*#
"Note that '.' representing any character includes spaces
"but not new lines, for example
REPLACE ALL OCCURRENCES OF PCRE `.` IN c WITH `#`.
*###
*###
*#
FIND PCRE `\n` IN c.
ASSERT sy-subrc = 0.
FIND PCRE `\r` IN c.
ASSERT sy-subrc = 0.
FIND PCRE `\t` IN c.
ASSERT sy-subrc = 4.
FIND ` ` IN c.
ASSERT sy-subrc = 4.
"In the followig string (that includes HTML tags), the content within
"the p tags shall be replaced. A new line is inlcuded.
"The first example just uses a non-greedy search with '.'.
"The example also demonstrates the replacement with groups. The regular
"expression contains three groups, and two of them shall be included in
"the repalcement.
DATA(html_a) = |<p>Hallo\n</p><p>Ciao!</p><p>Salut.</p>|.
DATA(html_b) = html_a.
REPLACE ALL OCCURRENCES OF PCRE `(<p>)(.*?)(<\/p>)` IN html_a WITH `$1Hi$3`.
*<p>Hallo
*</p><p>Hi</p><p>Hi</p>
"Regular expression: any character or a new line with zero or more repretitions
REPLACE ALL OCCURRENCES OF PCRE `(<p>)(.|\n)*?(<\/p>)` IN html_b WITH `$1Hi$3`.
*<p>Hi</p><p>Hi</p><p>Hi</p>
"The following strangely formatted demo HTML code is to be processed. It
"intentionally and randomly includes new lines and returns. Some HTML tags
"have attributes. Suppose you want to proceed with the following tasks:
"- Getting the content between the table tags
"- Putting the content in one line by removing all new lines and returns
"- Removing all attributes so that only the tags are available
DATA(nl) = |\n|.
DATA(rt) = |\r|.
DATA(html) =
`<html lang="EN">` && nl &&
`<body>` && nl &&
` <table border="1" summary="data display" ` && rt &&
`title="ABAP ` && nl &&
`Data">` &&
` <tr class="header">` && rt &&
` <th>CARRID` && nl &&
`</th>` && nl &&
` <th>CARRNAME</th>` &&
` </tr>` && nl &&
` <tr class="body">` && nl &&
` <td>` &&
` <span ` && nl &&
`class="nprpnwrp">XY</span>` &&
` </td>` && rt &&
` <td>` &&
` <span class="nprpnwrp"` && rt &&
`>XY Airlines</span>` && nl &&
` </td>` && nl &&
` </tr>` && nl &&
` <tr class="body">` && nl &&
` <td>` && rt &&
` <span class="nprpnwrp">YZ</span>` && rt &&
` </td>` && nl &&
` <td>` && nl &&
` <span class=` && rt &&
`"nprpnwrp">YZ Airways</span>` && nl &&
` </td>` && nl &&
` </tr>` && nl &&
` </table>` && rt &&
`</body>` && nl &&
`</html>`.
"See the following examples of how to proceed. Other regular expressions may be chosen, too.
"Getting the content/all tags between the table tags
"The regular expression considers the attributes of the table tag that could be anything.
"A non-greedy search up to the next '>' would not work with just '.' in this case because
"of the new lines and returns. So, a regular expression to retrieve the content might be
"as follows:
"[\s|\S]*?
"- Matches a single character specified within [...]
"- In this case it is either \s or \S (i.e. any whitespace or non-whitespace character
"- 'or' is represented by '|'
"- '*?' represents non-greedy search (zero or multiple occurrences) up to the next '>' in
" the example
"- The same regular expression is used between the <table ...> ... </table> tags to capture
" anyting.
"- It is put within a pair of parentheses to capture a group. This group (i.e. the offset
" and length values for the finding) is available in the data object following RESULTS
" in the FIND statement. As only one group is available in the regular expression,
" the 'submatches" table contains one line.
"- Note the escaping of '/' for '/' in </table>
"- The examples use FIND/REPLACE statements. You can also use string functions.
FIND PCRE `<table[\s|\S]*?>([\s|\S]*?)<\/table>` IN html RESULTS DATA(res).
DATA(content_bw_table_tag) = substring( val = html off = res-submatches[ 1 ]-offset len = res-submatches[ 1 ]-length ).
"Removing all new lines and returns
REPLACE ALL OCCURRENCES OF PCRE `\n|\r` IN content_bw_table_tag WITH ``.
"Removing all whitespace characters between start and end HTML tags
REPLACE ALL OCCURRENCES OF PCRE `>(\s*?)<` IN content_bw_table_tag WITH `><`.
"Removing all whitespace characters in front of the first HTML tag, and behind
"the last tag
REPLACE PCRE `^\s*?<` IN content_bw_table_tag WITH `<`.
REPLACE PCRE `>\s*$` IN content_bw_table_tag WITH `>`.
"Removing all attributes within tags
"Regex: Non-greedy searches up to the next whitespace character, and from that
"whitespace character up to the next '>'. Using $n, you refer to the capturing
"group. In this case, the first capturing group enclosed by '<...>' shall be
"inserted.
REPLACE ALL OCCURRENCES OF PCRE `<(.*?)\s(.*?)>` IN content_bw_table_tag WITH `<$1>`.
"span tags are not needed in the example any more as the attributes are removed
REPLACE ALL OCCURRENCES OF `<span>` IN content_bw_table_tag WITH ``.
REPLACE ALL OCCURRENCES OF `</span>` IN content_bw_table_tag WITH ``.
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
## More String Functions
As also covered in the [Misc Built-in Functions cheat sheet](24_Misc_Builtin_Functions.md), the following sections show more string functions available.

View File

@@ -34,7 +34,7 @@ This cheat sheet contains basic information about [unit testing](https://help.sa
## High-Level Steps for ABAP Unit Tests
- Identify dependend-on components (DOC) in your production code (i.e. your class/method) that need to be tested, and prepare the code for testing.
- Identify dependent-on components (DOC) in your production code (i.e. your class/method) that need to be tested, and prepare the code for testing.
- Examples of DOCs: In your production code, a method is called that is outside of your code. Or, for example, whenever there is an interaction with the database.
- This means that there are dependencies that need to be taken into account for a unit test. These dependencies should be isolated and replaced by a test double.
- Create/Implement test doubles
@@ -45,7 +45,7 @@ This cheat sheet contains basic information about [unit testing](https://help.sa
- Run unit tests
> **💡 Note**<br>
> Of course, if there are no dependend-on components in your production code, you can skip the considerations of dependency isolation, test doubles and their injection into the production code.
> In some examples, the code does not have any dependent-on components. Therefore, the considerations about dependency isolation, test doubles, and their injection into the code are skipped.
<p align="right"><a href="#top">⬆️ back to top</a></p>
@@ -270,7 +270,7 @@ ENDMETHOD.
Example: Test method for the example method *multiply_by_two* in the production code
As mentioned above, in simple cases, there may not be any dependend-on component in (a method of) the production code. Therefore, the functionality of the method in the production code is tested by simply comparing the value of the actual value (the value that is returned by the method, for example) and the expected value.
As mentioned above, in simple cases, there may not be any dependent-on component in (a method of) the production code. Therefore, the functionality of the method in the production code is tested by simply comparing the value of the actual value (the value that is returned by the method, for example) and the expected value.
``` abap
"The code in this snippet refers to the test class in the test include.
@@ -399,9 +399,9 @@ ENDCLASS.
## Handling Dependencies
The code snippets above covered test classes and methods in simple contexts without dependend-on components (DOC) in the production code. In more complex cases with dependencies in the production code, there are ways to deal with them. You can create test doubles and inject them into the production code during the test run.
The code snippets above covered test classes and methods in simple contexts without dependent-on components (DOC) in the production code. In more complex cases with dependencies in the production code, there are ways to deal with them. You can create test doubles and inject them into the production code during the test run.
It is assumed that you have identified the dependend-on components (DOC) in a method in your production code. They were isolated (which may have involved some major rebuilding if the code is not created from scratch and the requirements for unit testing were taken into account, e.g. by creating an interface), and you want to replace them with a test double (by injection) so that your code can be properly tested without dependencies.
It is assumed that you have identified the dependent-on components (DOC) in a method in your production code. They were isolated (which may have involved some major rebuilding if the code is not created from scratch and the requirements for unit testing were taken into account, e.g. by creating an interface), and you want to replace them with a test double (by injection) so that your code can be properly tested without dependencies.
**Creating/Implementing test doubles**

View File

@@ -18,7 +18,7 @@
- [Assigning References to Data Reference Variables](#assigning-references-to-data-reference-variables)
- [Creating Anonymous Data Objects](#creating-anonymous-data-objects)
- [Constants and Immutable Variables](#constants-and-immutable-variables)
- [Type Conversions and Assignments](#type-conversions-and-assignments)
- [Type Conversions, Compatibility and Assignments](#type-conversions-compatibility-and-assignments)
- [Terms Related to Data Types and Objects in a Nutshell](#terms-related-to-data-types-and-objects-in-a-nutshell)
- [Notes on the Declaration Context](#notes-on-the-declaration-context)
- [Excursions](#excursions)
@@ -1106,7 +1106,7 @@ SELECT * FROM zdemo_abap_carr INTO TABLE @FINAL(itab_final_inl).
<p align="right"><a href="#top">⬆️ back to top</a></p>
## Type Conversions and Assignments
## Type Conversions, Compatibility and Assignments
A value assignment means that the value of a data object is transferred to a target data object. If the data types of the source and target are compatible, the content is copied unchanged. If they are incompatible and a suitable [conversion rule](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_rule_glosry.htm) exists, the content is converted.
The following cases must be distinguished with regard to the data type:
- The source and target data types are compatible, i.e. all technical type properties match. The content is transferred from the source to the target without being converted.
@@ -1124,27 +1124,61 @@ See the conversion rules for the different data types here: [Assignment and Conv
```abap
"-------------------- Conversions --------------------
"Implicit conversions of the types c and string
DATA do_1_str TYPE string VALUE `abcedf`.
DATA do_1_str TYPE string VALUE `abcdef`.
DATA do_2_c3 TYPE c LENGTH 3.
"'abc'
do_2_c3 = do_1_str.
"Result: do_2_c3: 'abc'
"Implicit conversions of the types i and decfloat34
DATA do_4_i TYPE i.
DATA do_5_dcfl34 TYPE decfloat34 VALUE '4.56'.
"5
do_4_i = do_5_dcfl34.
"Result: do_4_i: 5
"Explicitly converting decfloat34 to i
DATA do_6_dcfl34 TYPE decfloat34 VALUE '2.78'.
"3
DATA(do_7_i) = CONV i( do_6_dcfl34 ).
"Result: do_7_i: 3
"Note conversions according to the rules, e.g. from
"Note the conversion rules in the ABAP Keyword Documentation, e.g. from
"type i to string
"`10-`
DATA(i2str) = CONV string( -10 ).
"Result: i2str: `10-`
"-------------------- Compatibility --------------------
"1. Source and target are compatible, all technical type properties
" match
DATA some_dobj TYPE c LENGTH 1 VALUE 'A'.
DATA flag TYPE abap_bool VALUE 'X'.
"Assignment of compatible types; content transferred without
"conversion
some_dobj = flag.
"2. Source and target are not compatible but can be converted.
" Content of source is converted according to conversion rules
" and then transferred to the target. Two data types are
" convertible if a conversion rule exists for them.
DATA another_char TYPE c LENGTH 3 VALUE 'abc'.
DATA some_str TYPE string VALUE `defghij`.
another_char = some_str.
"3. Data objects are neither compatible nor convertible. No
" assignment possible. If recognized by the syntax check, a
" syntax error is raised, otherwise an uncatchable exception
" is raised when the program is executed.
DATA some_number TYPE i VALUE 123.
DATA itab_str TYPE string_table.
"Type conversion not possible
"itab_str = some_number.
"some_number = itab_str.
```
<p align="right"><a href="#top">⬆️ back to top</a></p>

View File

@@ -23,7 +23,7 @@ It provides references to more detailed information on the topic.
- Access to SAP-delivered repository objects is restricted to objects released for ABAP for Cloud Development
- For example, most of the database tables provided by SAP cannot be read directly (although there are abstractions/[CDS entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm) for many that can be accessed).
- Libraries are available with predefined functionality.
- Note that repository objects can be classified by a [release contract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrelease_contract_glosry.htm) (e.g. C0, C1 etc.).
- Note that repository objects can be classified by a [release contract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrelease_contract_glosry.htm) (e.g. C0, C1 etc.). Find more information [here](https://help.sap.com/docs/ABAP_PLATFORM_NEW/c238d694b825421f940829321ffa326a/c479660d07374c15a1a5fe83fdbb1337.html?locale=en-US).
- Tools:
- [ABAP development tools for Eclipse (ADT)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm) are the only supported tools
- There is no access to SAP GUI (transactions `SE80`, `SE24` etc. you may know from classic ABAP)