La bibliotheque XCO (Extension Components) est une collection d’APIs moderne et orientee objet dans ABAP Cloud qui permet l’acces programmatique aux objets du repository et aux metadonnees. Avec XCO, vous pouvez lire les objets DDIC, analyser les vues CDS, gerer les packages et meme generer des objets de developpement.
Qu’est-ce que XCO ?
XCO signifie Extension Components et fournit une API unifiee et compatible cloud pour :
| Domaine XCO | Description | Classe principale |
|---|---|---|
| DDIC | Objets Data Dictionary | XCO_CP_ABAP_DICTIONARY |
| CDS | Vues Core Data Services | XCO_CP_CDS |
| Repository | Packages, Transport | XCO_CP_ABAP_REPOSITORY |
| Generation | Generation d’objets | XCO_CP_GENERATION |
| System | Infos systeme, User | XCO_CP |
Avantages de XCO
- Cloud-ready : Toutes les APIs sont released pour ABAP Cloud (C1)
- Interface fluide : Appels de methodes lisibles et chainables
- API coherente : Patterns uniformes dans tous les domaines
- Type-safe : Typage fort avec enumerations
XCO pour les objets DDIC
Lire les tables de base de donnees
Avec XCO, vous pouvez lire les metadonnees des tables de base de donnees au moment de l’execution :
CLASS zcl_xco_ddic_example DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS zcl_xco_ddic_example IMPLEMENTATION.
METHOD if_oo_adt_classrun~main. " Lire la table DATA(lo_table) = xco_cp_abap_dictionary=>database_table( 'SFLIGHT' ).
" Verifier si la table existe IF lo_table->exists( ). " Lire le contenu de la table (champs) DATA(lt_fields) = lo_table->fields->all->get( ).
LOOP AT lt_fields INTO DATA(lo_field). DATA(lv_field_name) = lo_field->name. DATA(lv_data_element) = lo_field->content( )->get_data_element( )->name.
out->write( |Champ: { lv_field_name } -> { lv_data_element }| ). ENDLOOP.
" Determiner le type de table DATA(lv_delivery_class) = lo_table->content( )->get_delivery_class( )->value. out->write( |Delivery Class: { lv_delivery_class }| ). ENDIF. ENDMETHOD.
ENDCLASS.Analyser les elements de donnees
" Lire l'element de donneesDATA(lo_data_element) = xco_cp_abap_dictionary=>data_element( 'CARRID' ).
IF lo_data_element->exists( ). " Obtenir le contenu DATA(lo_content) = lo_data_element->content( ).
" Determiner le domaine DATA(lv_domain) = lo_content->get_domain( )->name.
" Lire les libelles de champ DATA(ls_short_text) = lo_content->get_short_text( ). DATA(ls_medium_text) = lo_content->get_medium_text( ). DATA(ls_long_text) = lo_content->get_long_text( ).
out->write( |Domaine: { lv_domain }| ). out->write( |Texte court: { ls_short_text-text }| ).ENDIF.Domaines avec valeurs fixes
" Lire le domaine avec valeurs fixesDATA(lo_domain) = xco_cp_abap_dictionary=>domain( 'S_CONN_TYPE' ).
IF lo_domain->exists( ). " Lire les Fixed Values DATA(lt_fixed_values) = lo_domain->fixed_values->all->get( ).
LOOP AT lt_fixed_values INTO DATA(lo_fixed_value). DATA(lv_low) = lo_fixed_value->value. DATA(lv_description) = lo_fixed_value->content( )->get_description( ).
out->write( |{ lv_low }: { lv_description }| ). ENDLOOP.ENDIF.XCO pour les vues CDS
XCO permet de lire les metadonnees des vues CDS, y compris les champs, les associations et les annotations.
Lire les champs d’une vue CDS
CLASS zcl_xco_cds_example DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS zcl_xco_cds_example IMPLEMENTATION.
METHOD if_oo_adt_classrun~main. " Lire la View Entity CDS DATA(lo_view) = xco_cp_cds=>view_entity( 'I_PRODUCT' ).
IF lo_view->exists( ). out->write( '=== Vue CDS: I_PRODUCT ===' ).
" Tous les champs de la vue DATA(lt_fields) = lo_view->fields->all->get( ).
out->write( |Nombre de champs: { lines( lt_fields ) }| ).
LOOP AT lt_fields INTO DATA(lo_field). DATA(lv_name) = lo_field->name. DATA(lo_content) = lo_field->content( ).
" Determiner le type de donnees (si disponible) TRY. DATA(lv_data_element) = lo_content->get_data_element( )->name. out->write( | { lv_name } -> { lv_data_element }| ). CATCH cx_root. out->write( | { lv_name } (pas de Data Element)| ). ENDTRY. ENDLOOP. ELSE. out->write( 'La vue n''existe pas.' ). ENDIF. ENDMETHOD.
ENDCLASS.Lire les associations
" Vue CDS avec associationsDATA(lo_view) = xco_cp_cds=>view_entity( 'I_SALESORDER' ).
IF lo_view->exists( ). " Toutes les associations de la vue DATA(lt_associations) = lo_view->associations->all->get( ).
LOOP AT lt_associations INTO DATA(lo_assoc). DATA(lv_assoc_name) = lo_assoc->name. DATA(lo_target) = lo_assoc->content( )->get_target( ). DATA(lv_target_name) = lo_target->name.
" Cardinalite DATA(lo_cardinality) = lo_assoc->content( )->get_cardinality( ). DATA(lv_min) = lo_cardinality->min. DATA(lv_max) = lo_cardinality->max.
out->write( |Association { lv_assoc_name } -> { lv_target_name }| ). out->write( | Cardinalite: [{ lv_min }..{ lv_max }]| ). ENDLOOP.ENDIF.Lire les annotations
" Lire les annotations d'une vue CDSDATA(lo_view) = xco_cp_cds=>view_entity( 'I_BUSINESSPARTNER' ).
IF lo_view->exists( ). " Annotations au niveau de la vue DATA(lt_annotations) = lo_view->annotations->all->get( ).
LOOP AT lt_annotations INTO DATA(lo_annotation). DATA(lv_anno_name) = lo_annotation->name.
TRY. DATA(lv_value) = lo_annotation->value->get_string( ). out->write( |@{ lv_anno_name }: { lv_value }| ). CATCH cx_root. out->write( |@{ lv_anno_name }: (valeur complexe)| ). ENDTRY. ENDLOOP.ENDIF.XCO pour les packages et le transport
Lire les informations de package
CLASS zcl_xco_package_example DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS zcl_xco_package_example IMPLEMENTATION.
METHOD if_oo_adt_classrun~main. " Lire le package DATA(lo_package) = xco_cp_abap_repository=>package->for( 'ZRAP_DEMO' ).
IF lo_package->exists( ). " Attributs du package DATA(lo_content) = lo_package->read( ). DATA(lv_description) = lo_content-short_description. DATA(lv_sw_component) = lo_content-software_component.
out->write( |Package: ZRAP_DEMO| ). out->write( |Description: { lv_description }| ). out->write( |Composant logiciel: { lv_sw_component }| ).
" Lister les objets du package out->write( '--- Objets du package ---' ).
" Classes DATA(lt_classes) = lo_package->objects->where( xco_cp_abap=>object_type->clas )->all->get( ). LOOP AT lt_classes INTO DATA(lo_class). out->write( |CLAS: { lo_class->name }| ). ENDLOOP.
" Vues CDS DATA(lt_ddls) = lo_package->objects->where( xco_cp_abap=>object_type->ddls )->all->get( ). LOOP AT lt_ddls INTO DATA(lo_ddls). out->write( |DDLS: { lo_ddls->name }| ). ENDLOOP. ENDIF. ENDMETHOD.
ENDCLASS.Informations de transport
" Lire l'ordre de transportDATA(lo_transport) = xco_cp_cts=>transport->for( 'NPLK900001' ).
IF lo_transport->exists( ). DATA(lo_properties) = lo_transport->properties( ).
DATA(lv_owner) = lo_properties->get_owner( ). DATA(lv_description) = lo_properties->get_description( ). DATA(lv_status) = lo_properties->get_status( )->value.
out->write( |Transport: NPLK900001| ). out->write( |Proprietaire: { lv_owner }| ). out->write( |Statut: { lv_status }| ).ENDIF.
" Transports systeme actuels de l'utilisateurDATA(lt_transports) = xco_cp_cts=>transports->modifiable->owned_by( xco_cp=>sy->user( ))->where( xco_cp_transport=>type->request)->all->get( ).
LOOP AT lt_transports INTO DATA(lo_my_transport). out->write( |Mon transport: { lo_my_transport->value }| ).ENDLOOP.Generation d’objets de developpement
XCO permet egalement la generation programmatique d’objets ABAP - une fonctionnalite puissante pour les generateurs et les templates.
Generer une classe
CLASS zcl_xco_generation_example DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. METHODS generate_class IMPORTING iv_class_name TYPE sxco_ao_object_name iv_package TYPE sxco_package iv_transport TYPE sxco_transport RAISING cx_xco_gen_put_exception.
ENDCLASS.
CLASS zcl_xco_generation_example IMPLEMENTATION.
METHOD generate_class. " Environnement de generation pour le transport DATA(lo_environment) = xco_cp_generation=>environment->dev_system( iv_transport ).
" Preparer l'operation PUT DATA(lo_put) = lo_environment->create_put_operation( ).
" Specifier la classe DATA(lo_class_spec) = lo_put->for-clas->add_object( iv_class_name )->set_package( iv_package )->create_form_specification( ).
" Definition de la classe lo_class_spec->set_short_description( 'Generated by XCO' ). lo_class_spec->definition->set_final( ). lo_class_spec->definition->set_create_public( ).
" Ajouter une interface lo_class_spec->definition->add_interface( 'IF_OO_ADT_CLASSRUN' ).
" Section publique avec methode lo_class_spec->definition->section-public->add_method( 'PROCESS" )->set_returning( VALUE #( data_type = xco_cp_abap=>type-built_in->string ) ).
" Implementation lo_class_spec->implementation->add_method( 'IF_OO_ADT_CLASSRUN~MAIN" )->set_source( VALUE #( ( `out->write( 'Hello from generated class!' ).` ) ) ).
lo_class_spec->implementation->add_method( 'PROCESS" )->set_source( VALUE #( ( `result = |Processed at { sy-datum }|.` ) ) ).
" Executer la generation lo_put->execute( ). ENDMETHOD.
ENDCLASS.Generer une interface
METHOD generate_interface. DATA(lo_environment) = xco_cp_generation=>environment->dev_system( iv_transport ).
DATA(lo_put) = lo_environment->create_put_operation( ).
" Specifier l'interface DATA(lo_intf_spec) = lo_put->for-intf->add_object( 'ZIF_GENERATED" )->set_package( 'ZPACKAGE" )->create_form_specification( ).
lo_intf_spec->set_short_description( 'Generated Interface' ).
" Ajouter des methodes lo_intf_spec->add_method( 'GET_DATA" )->set_returning( VALUE #( data_type = xco_cp_abap=>type-built_in->string ) ).
lo_intf_spec->add_method( 'SET_DATA" )->add_parameter( 'IV_VALUE" )->set_importing( )->set_data_type( xco_cp_abap=>type-built_in->string ).
lo_put->execute( ).ENDMETHOD.Generer une table de base de donnees
METHOD generate_table. DATA(lo_environment) = xco_cp_generation=>environment->dev_system( iv_transport ).
DATA(lo_put) = lo_environment->create_put_operation( ).
" Specifier la table DATA(lo_table_spec) = lo_put->for-tabl-for-database_table->add_object( 'ZGENERATED_TAB" )->set_package( 'ZPACKAGE" )->create_form_specification( ).
lo_table_spec->set_short_description( 'Generated Table' ). lo_table_spec->set_delivery_class( xco_cp_database_table=>delivery_class->a ). lo_table_spec->set_data_maintenance( xco_cp_database_table=>data_maintenance->allowed ).
" Ajouter des champs lo_table_spec->add_field( 'CLIENT" )->set_type( xco_cp_abap_dictionary=>data_element( 'MANDT' ) )->set_key_indicator( ).
lo_table_spec->add_field( 'ID" )->set_type( xco_cp_abap_dictionary=>built_in_type->numc( 10 ) )->set_key_indicator( ).
lo_table_spec->add_field( 'DESCRIPTION" )->set_type( xco_cp_abap_dictionary=>data_element( 'TEXT255' ) ).
lo_table_spec->add_field( 'CREATED_AT" )->set_type( xco_cp_abap_dictionary=>data_element( 'TIMESTAMPL' ) ).
lo_put->execute( ).ENDMETHOD.Exemple pratique : generateur de documentation
Cet exemple montre comment generer automatiquement une documentation pour tous les objets d’un package avec XCO :
CLASS zcl_package_documentation DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_oo_adt_classrun.
METHODS generate_documentation IMPORTING iv_package TYPE sxco_package RETURNING VALUE(rt_doc) TYPE string_table.
ENDCLASS.
CLASS zcl_package_documentation IMPLEMENTATION.
METHOD if_oo_adt_classrun~main. DATA(lt_documentation) = generate_documentation( 'ZRAP_DEMO' ).
LOOP AT lt_documentation INTO DATA(lv_line). out->write( lv_line ). ENDLOOP. ENDMETHOD.
METHOD generate_documentation. DATA(lo_package) = xco_cp_abap_repository=>package->for( iv_package ).
IF NOT lo_package->exists( ). APPEND |Package { iv_package } non trouve.| TO rt_doc. RETURN. ENDIF.
APPEND |# Documentation Package: { iv_package }| TO rt_doc. APPEND || TO rt_doc.
" Documenter les classes APPEND |## Classes| TO rt_doc. DATA(lt_classes) = lo_package->objects->where( xco_cp_abap=>object_type->clas )->all->get( ).
LOOP AT lt_classes INTO DATA(lo_class_obj). DATA(lo_class) = xco_cp_abap=>class( CONV #( lo_class_obj->name ) ).
IF lo_class->exists( ). DATA(lo_class_content) = lo_class->content( ). DATA(lv_description) = lo_class_content->get_short_description( ).
APPEND |### { lo_class_obj->name }| TO rt_doc. APPEND |{ lv_description }| TO rt_doc. APPEND || TO rt_doc.
" Lister les methodes publiques DATA(lt_methods) = lo_class->definition->section-public->components->method->all->get( ). IF lt_methods IS NOT INITIAL. APPEND |**Methodes publiques:**| TO rt_doc. LOOP AT lt_methods INTO DATA(lo_method). APPEND |- { lo_method->name }| TO rt_doc. ENDLOOP. APPEND || TO rt_doc. ENDIF. ENDIF. ENDLOOP.
" Documenter les vues CDS APPEND |## Vues CDS| TO rt_doc. DATA(lt_ddls) = lo_package->objects->where( xco_cp_abap=>object_type->ddls )->all->get( ).
LOOP AT lt_ddls INTO DATA(lo_ddls_obj). DATA(lo_view) = xco_cp_cds=>view_entity( CONV #( lo_ddls_obj->name ) ).
IF lo_view->exists( ). DATA(lt_fields) = lo_view->fields->all->get( ).
APPEND |### { lo_ddls_obj->name }| TO rt_doc. APPEND |Champs: { lines( lt_fields ) }| TO rt_doc. APPEND || TO rt_doc. ENDIF. ENDLOOP.
" Documenter les interfaces APPEND |## Interfaces| TO rt_doc. DATA(lt_intfs) = lo_package->objects->where( xco_cp_abap=>object_type->intf )->all->get( ).
LOOP AT lt_intfs INTO DATA(lo_intf_obj). APPEND |- { lo_intf_obj->name }| TO rt_doc. ENDLOOP. ENDMETHOD.
ENDCLASS.Bonnes pratiques
1. Verification d’existence
Verifiez toujours si un objet existe avant d’y acceder :
DATA(lo_table) = xco_cp_abap_dictionary=>database_table( 'ZTABLE' ).
IF lo_table->exists( ). " Acces securise DATA(lo_content) = lo_table->content( ).ENDIF.2. Gestion des exceptions
TRY. DATA(lv_value) = lo_annotation->value->get_string( ). CATCH cx_xco_runtime_exception INTO DATA(lx_error). " Annotation complexe ou autre erreur DATA(lv_message) = lx_error->get_text( ).ENDTRY.3. Utiliser l’interface fluide
XCO est optimise pour les appels chaines :
" Bon: FluideDATA(lt_public_methods) = xco_cp_abap=>class( 'ZCL_MYCLASS" )->definition->section-public->components->method->all->get( ).
" Moins bon: Beaucoup de variables intermediairesDATA(lo_class) = xco_cp_abap=>class( 'ZCL_MYCLASS' ).DATA(lo_definition) = lo_class->definition.DATA(lo_public) = lo_definition->section-public." ...4. Performance pour les operations en masse
" Pour de nombreux objets: filtrer d'abord, puis lireDATA(lt_classes) = lo_package->objects->where( xco_cp_abap=>object_type->clas)->where( xco_cp_object=>object_name->range( VALUE #( sign = 'I' option = 'CP' low = 'ZCL_*' )) )->all->get( ).Apercu XCO : points d’entree importants
| Point d’entree | Description |
|---|---|
XCO_CP_ABAP_DICTIONARY | DDIC : Tables, Views, Elements de donnees, Domaines |
XCO_CP_CDS | Vues CDS, Entities, Abstracts |
XCO_CP_ABAP | Classes, Interfaces, Types d’objets |
XCO_CP_ABAP_REPOSITORY | Packages, Objets du repository |
XCO_CP_CTS | Change and Transport System |
XCO_CP_GENERATION | Generation d’objets |
XCO_CP | Systeme, User, Utilitaires |
Conclusion
La bibliotheque XCO est un outil indispensable pour le developpement ABAP Cloud avance :
- Analyse des metadonnees : Comprendre la structure de votre systeme par programmation
- Generateurs de code : Automatiser la creation d’objets de developpement
- Documentation : Generer automatiquement de la documentation technique
- Outillage : Construire vos propres outils de developpement
Avec l’interface fluide et la structure API coherente, XCO est a la fois puissant et agreable a utiliser.