Services WEB/REST

En standard, beCPG propose un service HTTP REST appelé Remote API qui permet :

  • d'importer les données d'une entité au format Xml,
  • d'exporter les données d'une entité au format Xml selon des critères (Ex : je souhaite tous les produits qui sont validés et effectifs à la date DD/MM/YYYY).

Ce service REST permet de réaliser des interfaces avec des logiciels tiers tel que l'ERP. Par entité, on entend le produit, le client, le fournisseur, le projet, etc... avec l'ensemble de ses informations et cela de manière dynamique sans développement.

L'interface d'échange peut donc être réalisée par un outil tiers dont le rôle est de :

  • piloter les échanges,
  • transformer les flux (règles de transformation sur des listes de valeurs par exemple),
  • gérer les erreurs. Cette outil tiers dialogue avec la Remote API pour importer et exporter les données de beCPG. 2 approches sont possibles :
  • le client possède un outil tiers permettant de réaliser l'interface,
  • le client souhaite que beCPG mette en place un outil tiers permettant de réaliser l'interface. Par ailleurs, toutes les API de l'application sont accessibles par services REST :
  • opérations CRUD, Create/Read/Update/Delete
  • formulation
  • génération documentaire
  • récupération des versions, des fiches techniques
  • etc...

API beCPG

La remote API de beCPG propose les URL REST suivantes:

<url>/becpg/remote/entity/list?path={path}</url>
<url>/becpg/remote/entity/list?query={query}&maxResults={maxResults}</url>
<url>/becpg/remote/entity?nodeRef={nodeRef}</url>
<url>/becpg/remote/entity?path={path}</url>
<url>/becpg/remote/entity?query={query}</url>
<url>/becpg/remote/formulate?nodeRef={nodeRef}</url>
<url>/becpg/remote/formulate?path={path}</url>
<url>/becpg/remote/formulate?query={query}</url>
<url>/becpg/remote/merge?nodeRef={nodeRef}</url>
<url>/becpg/remote/branch?nodeRef={nodeRef}</url>
<url>/becpg/remote/report?nodeRef={nodeRef}&tplNodeRef={tplNodeRef}</url>
<url>/becpg/remote/report?nodeRef={nodeRef}&tplNodeRef={tplNodeRef}&locale={locale}</url>
<url>/becpg/remote/report?nodeRef={nodeRef}&tplNodeRef={tplNodeRef}&locale={locale}&format={format}</url>

Les méthodes POST/GET/PUT/DELETE permettent respectivement d'ajouter, retrouver, mettre à jour et supprimer des entités dans le PLM (produit, client, fournisseur, etc ..).

Lister les entités

La liste des entités est obtenue avec la requête LIST et peut être filtrée suivant des critères de recherche avancés (dernier produit modifié depuis une date spécifiée par exemple).

<url>/becpg/remote/entity/list?path={path}</url>
<url>/becpg/remote/entity/list?query={query}&maxResults={maxResults}&fields={fields}</url>
<url>/becpg/remote/entity/list?path={path}&maxResults={maxResults}&fields={fields}</url>

La syntaxe de recherche est la syntaxe Lucène FTS Alfresco 1 : http://docs.alfresco.com/5.0/concepts/rm-searchsyntax-intro.html

1. Vous pouvez aussi vous référer à la partie Construction de requêtes Lucène de la documentation

Un exemple de requête permettant d'avoir un produit fini suivant son code erp :

+TYPE:"bcpg:finishedProduct" AND +@bcpg\\:erpCode:"codeErp" AND -ASPECT:"bcpg:compositeVersion"
(-ASPECT:"bcpg:compositeVersion" permet d'exclure les versions antérieur)

L'Url correspondante :

http://localhost:8080/alfresco/service/becpg/remote/entity?query=%2BTYPE%3A%22bcpg%3AfinishedProduct%22%20AND%20%2B%40bcpg%5C%3AerpCode%3A%22codeErp%22%20AND%20-ASPECT%3A%22bcpg%3AcompositeVersion%22

Pour obtenir l'URL encodé (dans la console de firefox):

encodeURIComponent('+TYPE:"bcpg:finishedProduct" AND +@bcpg\\:erpCode:"codeErp" AND -ASPECT:"bcpg:compositeVersion"')

Le paramètre maxResults permet de spécifier un nombre de résultat (-1 pour avoir tous les résultats)

Le paramètre format permet de modifier le format XML de la réponse

  • format=xml (Par défaut)
  • format=json (Format json)

Le paramètre fields permet de spécifier des champs ou des associations à extraire dans les résultats :

http://localhost/alfresco/service/becpg/remote/entity/list?query=%2BTYPE%3A%22bcpg%3AfinishedProduct%22&fields=bcpg:legalName,bcpg:clients

Exemples :

Exemple de script bash permettant de récupérer directement sous forme de fichier xml une liste d'entités :

#!/bin/sh

export REMOTE_SERVER=http://localhost:8080/alfresco/service/becpg/remote/entity
export REMOTE_USER=admin
echo "Entrez le mots de passe"
read REMOTE_PASSWORD=

#Récupération de la liste des noeuds :

wget --quiet --http-user=$REMOTE_USER --http-password=$REMOTE_PASSWORD  --header=Accept-Charset:iso-8859-1,utf-8 --header=Accept-Language:en-us -O list.xml $REMOTE_SERVER/list 
count=1

#On parcourt la liste
while [ -n "$nodeRef" -o $count = 1 ]
   do
      nodeRef=`cat list.xml | xpath -q -e //*[$count]/@nodeRef | sed s/nodeRef=//g |sed s/\"//g`
      echo "\Obtention du noeud $nodeRef"; 
      #On enregistre chaque noeud
      wget --quiet --http-user=$REMOTE_USER --http-password=$REMOTE_PASSWORD  --header=Accept-Charset:iso-8859-1,utf-8 --header=Accept-Language:en-us -O entity_$count.xml $REMOTE_SERVER?nodeRef=$nodeRef
      count=$((count+1))
done

Obtenir une entité

Pour l'obtention d'entités, deux services REST sont disponibles :

La remote API en utilisant des requêtes de TYPE GET suivantes

<url>/becpg/remote/entity?nodeRef={nodeRef}&format={format}</url>
 <url>/becpg/remote/entity?path={path}&format={format}</url>
 <url>/becpg/remote/entity?query={query}&format={format}</url>
 <url>/becpg/remote/entity?nodRef={nodeRef}&lists={lists}&fields={fields}</url>
 <url>/becpg/remote/entity?path={path}&lists={lists}&fields={fields}</url>
 <url>/becpg/remote/entity?query={query}&lists={lists}&fields={fields}</url>

Le paramètre format permet de modifier le format XML de la réponse :

  • format=xml (Par défaut)
  • format=json (Format json))
  • format=xml_all (Contient le détails de toutes les associations)
  • format=xml_excel (Format adapter pour l'utilisation comme datasource dans excel)
  • format=xml_light (Ce format ne contient pas les associations de type enfants)
  • format=xsd (Ce format permet d'extraire la XSD)
  • format=xsd_excel (Ce format permet d'extraire la XSD pour excel)

Vous pouvez également passer des paramètres supplémentaires de filtrage pour alléger la réponse. Il y a 3 types de filtrage :

  • Filtrage des Propriétés : inclus uniquement les propriétés listées (fields=bcpg:legalName)
  • Filtrage des Associations : inclus uniquement les associations listées (fields=bcpg:clients)
  • Filtrage des Listes : inclus uniquement les listes listées (lists=bcpg:compoList)

Par ailleurs, vous pouvez extraire les propriétés d'une association en passant dans le paramètre fields le nom des associations et leurs propriétés, en respectant le format suivant : ASSOC_Name1|PROP_Name1,ASSOC_Name1|PROP_Name2.

Exemple

http://localhost/alfresco/service/becpg/remote/entity?nodeRef=workspace://SpacesStore/9b4dd09a-afaa-41ec-84eb-db062146975c&fields=bcpg:legalName,bcpg:clients,bcpg:compoListProduct|bcpg:productState&lists=bcpg:compoList

L'API Rapport

<url>/becpg/report/datasource?nodeRef={nodeRef}</url>

L'API rapport effectue un retravail de la donnée et permet d'obtenir un XML plus facile à exploiter. Les données de formulation, tare, coût, ainsi que les listes multi-niveaux sont directement exploitables. Cette API est conseillée si vous souhaitez extraire des données produits. Cette API est moins performante.

Mettre à jour une entité

La mise à jour et la création d'une entité sont réalisées en utilisant les méthodes PUT (Création) et POST (Mise à jour) et les requètes suivantes :

<url>/becpg/remote/entity?nodeRef={nodeRef}</url>
<url>/becpg/remote/entity?path={path}</url>
<url>/becpg/remote/entity?query={query}</url>
<url>/becpg/remote/entity?nodeRef={nodeRef}&createVersion=true&majorVersion={majorVersion}&versionDescription={description}</url>

Le contenu de la requête doit contenir un XML au format par défaut de la remote API. Il n'est pas nécessaire d'avoir tous les champs. Seuls les champs présents sont créés/mis à jour.

Lorsque createVersion=true alors majorVersion (true/false) et versionDescription permettent de créer une nouvelle version de l'entité à mettre à jour.

Exemple:

Exemple de requête CURL pour créer une entité

curl --user username:password -H "Content-Type: application/xml"  -X PUT --data @sample-entity.xml  http://localhost/alfresco/service/becpg/remote/entity?format=json

Exemple de XML permettant de créer un projet sample-entity.xml

<?xml version='1.0' encoding='UTF-8'?>
<pjt:project xmlns:pjt="http://www.bcpg.fr/model/project/1.0" path="/app:company_home/st:sites/cm:simulation/cm:documentLibrary"
    type="node" name="Sample project">
    <pjt:projectPriority type="d:int"><![CDATA[2]]></pjt:projectPriority>
    <cm:description xmlns:cm="http://www.alfresco.org/model/content/1.0" type="d:mltext" fr="Texte - texte -texte"><![CDATA[Texte - texte -texte]]></cm:description>
    <cm:name xmlns:cm="http://www.alfresco.org/model/content/1.0" type="d:text"><![CDATA[Sample project]]></cm:name>
    <cm:title xmlns:cm="http://www.alfresco.org/model/content/1.0" type="d:mltext" fr="Sample project"><![CDATA[Sample project]]></cm:title>
    <pjt:projectState type="d:text"><![CDATA[Planned]]></pjt:projectState>
</pjt:project>

Vous pouvez également utiliser le format JSON qui est le format conseillé pour la création et la mise à jour à partir de la version 3.2. Ce format a l'avantage de permettre la mise à jour de certains champs impossible auparavant.

curl --user username:password -H "Content-Type: application/json"  -X PUT --data @sample-json.json  http://localhost/alfresco/service/becpg/remote/entity

Pour chaque élément, la racine définit les clés sur lesquelles rechercher un élément et attributes permet de spécifier les valeurs à mettre à jour.

Exemple :

{
    "entity": {
        "bcpg:erpCode": "TEST-REMOTE001",
        "cm:name":"Test remote",
        "type": "bcpg:finishedProduct",
        "params" : {
            "replaceExistingLists" : true,
            "dataListsToReplace": "bcpg:allergenList,bcpg:compoList"
        },
        "attributes": {
                 "bcpg:legalName_en": "Legal Produit fini EN",
                 "bcpg:legalName": "Legal Produit fini FR",
                 "bcpg:clients": [
                        {
                            "bcpg:code": "C1"
                        },
                        {
                            "bcpg:code": "C2"
                        }
                    ],

                  "bcpg:productHierarchy2": {
                    "path": "/app:company_home/cm:System/cm:ProductHierarchy/bcpg:entityLists/cm:finishedProduct_Hierarchy",
                    "bcpg:lkvValue": "Pizza",
                    "type": "bcpg:linkedValue"
                }  
            },
        "datalists": {
          "bcpg:allergenList": [
                {
                    "bcpg:allergenListAllergen": {
                         "bcpg:charactName": "Allergen 4"
                    },
                    "attributes": {
                        "bcpg:allergenListVoluntary": false,
                        "bcpg:allergenListInVoluntary": true
                    },
                    "type": "bcpg:allergenList"
                }
            ],
          "bcpg:compoList": [
                {
                     "bcpg:compoListProduct": {
                            "bcpg:code": "LSF411"
                     },
                    "attributes": {
                        "bcpg:compoListQtySubFormula": 15,
                        "bcpg:compoListUnit": "kg"
                    }
                },
                 {
                     "bcpg:compoListProduct": {
                            "bcpg:erpCode": "TEST1"
                     },
                    "attributes": {
                        "bcpg:compoListQtySubFormula": 10,
                        "bcpg:compoListUnit": "kg"
                    }
                }
        ]
        }
    }
}

L'attribut params permet de passer certains paramètres à l'API:

  • replaceExistingLists (false) : Permet de supprimer les lignes dans les listes non présentes dans le fichier JSON
  • dataListsToReplace ("") : Permet de supprimer les lignes dans certains listes uniquement

Mettre à jour une propriété multi-langue

Vous pouvez importer les champs de type mltext en spécifiant pour chaque langue la valeur :

<cm:title xmlns:cm="http://www.alfresco.org/model/content/1.0" type="d:mltext" de="Beispielprojekt" fr="Exemple de projet" en="Sample project"><![CDATA[Sample project]]></cm:title>

En json la propriété est suivie d'un underscore et du code de la langue

"bcpg:legalName_en_US": "Valeur US"    

Mettre à jour une association

Une association peut être identifiée par son nodeRef, son nom, son code (beCPG ou ERP) et son chemin

N.B : Dans les précédentes versions < 2.2.X, il faut fournir un nodeRef factice.

Exemple : l'association entité d'un projet

<pjt:projectEntity type="assoc"><bcpg:finishedProduct type="node" name="ENTITY_NAME" code="BCPG_CODE" nodeRef="FAKE_NODEREF"></bcpg:finishedProduct></pjt:projectEntity>

Supprimer une entité

La remote API permet de supprimer des entités en utilisant des requêtes de TYPE DELETE suivantes:

<url>/becpg/remote/entity?nodeRef={nodeRef}&format={format}</url>
 <url>/becpg/remote/entity?path={path}&format={format}</url>
 <url>/becpg/remote/entity?query={query}&format={format}</url>

Exemple de script permettant de supprimer en masse des entités (Toutes les matières)

#!/bin/sh
export REMOTE_SERVER=http://localhost/alfresco/service/becpg/remote/entity
export REMOTE_USER=admin
echo "Entrez le mots de passe"
read REMOTE_PASSWORD=

if [ $# -ne 1 ]
   then
                #LIST
                wget --quiet --http-user=$REMOTE_USER --http-password=$REMOTE_PASSWORD  --header=Accept-Charset:iso-8859-1,utf-8 --header=Accept-Language:en-us -O list.xml $REMOTE_SERVER/list?query=%2BTYPE%3A%22bcpg%3ArawMaterial%22%20-ASPECT%3A%22sys%3Atemporary%22%20-ASPECT%3A%22bcpg%3AentityTplAspect%22
                count=1

                while [ -n "$nodeRef" -o $count = 1 ]
                do
                   nodeRef=`cat list.xml | xpath -q -e //*[$count]/@nodeRef |sed s/nodeRef=//g|sed s/\"//g|sed s/\:\\\///g| xargs`

                 echo "DELETE ${nodeRef}";
                 curl --user $REMOTE_USER:$REMOTE_PASSWORD -X $REMOTE_SERVER?nodeRef=$nodeRef
                 count=$((count+1))
                done

      exit 0
fi

Obtenir une fiche technique

La remote API permet aussi de télécharger des rapports en utilisant GET suivantes:

<url>/becpg/remote/report?nodeRef={nodeRef}&tplNodeRef={tplNodeRef}</url>
<url>/becpg/remote/report?nodeRef={nodeRef}&tplNodeRef={tplNodeRef}&locale={locale}</url>
<url>/becpg/remote/report?nodeRef={nodeRef}&tplNodeRef={tplNodeRef}&locale={locale}&format={format}</url>
  • nodeRef étant l'identifiant système du produit
  • tplNodeRef étant l'identifiant du modèle de rapport
  • locale étant le code de la langue
  • format étant le format du rapport (PDF, XLSX, DOCX, ODT, ZIP)

De plus, il est possible de télécharger des rapports en spécifiant les paramètres au format JSON dans une requête POST

Exemple en utilisant l'outil CURL

    #!/bin/sh

    export LOCAL_SERVER=http://localhost/alfresco/service/becpg/remote/report
    export LOCAL_USER=admin
    export LOCAL_PASSWORD=becpg

    curl --user $LOCAL_USER:$LOCAL_PASSWORD -H "Content-Type: application/json"  -X POST --data @params.json  "$LOCAL_SERVER?nodeRef=$1&tplNodeRef=$2" > report.pdf

Les variables $1 et $2 sont respectivement l'identifiant du produit et l'identifiant du modèle de rapport. Le fichier params.json contient les paramètres :

    {
    iterationKey : "bcpg:plant",
    params : [{
    id: "param1",
    prop : "cm:name" 
    }],
    prefs : {
    assocsToExtract : "bcpg:plants,bcpg:suppliers,bcpg:storageConditionsRef,bcpg:precautionOfUseRef,bcpg:nutListNut",
    assocsToExtractWithDataList : "bcpg:compoListProduct" 
    },
    nameFormat : "{entity_cm:name}- {report_cm:name}  - {locale} - {param1} ",
    titleFormat : " {report_cm:name} -  {locale} - {param1}" 
    }

Pour plus de détails sur le paramétrage des rapports voir Extracteur - Partie 1

Créer et fusionner une branche

Les requêtes POST suivantes permettent respectivement de créer et fusionner une branche

<url>/becpg/remote/branch?nodeRef={nodeRef}&destNodeRef={destNodeRef?}</url>

destNodeRef est optionnel, par défaut la branche est créé dans le même dossier que l'entité.

<url>/becpg/remote/merge?nodeRef={nodeRef}&branchToNodeRef={branchToNodeRef?}&majorVersion={majorVersion?}&impactWused={impactWused?}</url>

Contenu de la requête:

{
 "description":"Branche description}
}

Utilitaire JAVA

beCPG fournit également une librairie utilitaire JAVA permettant de faciliter les appels aux services REST. Cette librairie peut être compilée depuis le code source :

https://www.becpg.fr/hg/becpg-tools (read-only:read-only)

ou obtenue sous forme de jar : becpg-tools.jar

Ci-dessous un exemple de classe java permettant de récupérer la liste des entités puis d'itérer chaque entité.

import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.HttpClient;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import fr.becpg.tools.http.GetEntityCommand;
import fr.becpg.tools.http.ListEntitiesCommand;

public class SampleInstanceImporter {
    private static Log logger = LogFactory.getLog(InstanceImporter.class);
    private String serverUrl;
    public InstanceImporter(String serverUrl) {
        super();
        this.serverUrl = serverUrl;
    }
    public void loadEntities(String query, HttpClient client) throws Exception {
        ListEntitiesCommand listEntitiesCommand = new ListEntitiesCommand(serverUrl);
        try (InputStream entitiesStream = listEntitiesCommand.runCommand(client, query)) {
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true); // never forget this!
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            Document doc = builder.parse(entitiesStream);
            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            int count = 1;
            String nodeRef = null;
            while ((nodeRef = (String) xpath.evaluate("//*[" + count + "]/@nodeRef", doc, XPathConstants.STRING)) != null && nodeRef.length() > 0) {
                count++;
                try {
                    loadEntity(client, nodeRef);
                } catch(Exception e){
                    logger.error("Invalid Xml for "+nodeRef+" skipping node");
                    if(logger.isDebugEnabled()){
                        logger.debug(e,e);
                     }
                 }
            }
         }
     }
    private void loadEntity(HttpClient client, String nodeRef) throws Exception {
        logger.info("Import nodeRef:" + nodeRef);
        GetEntityCommand getEntityCommand = new GetEntityCommand(serverUrl);
        try (InputStream entityStream = getEntityCommand.runCommand(client, nodeRef)) {
             //Parse XML and do ETL transformation
         }
    }
    public String buildQuery(Date lastImport) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
        String dateRange = "MIN";
        if (lastImport != null) {
            dateRange = dateFormat.format(lastImport);
         }
        logger.info("Import from :[ " + dateRange + " TO MAX ]");
        String query = "@cm\\:created:[%s TO MAX] OR @cm\\:modified:[%s TO MAX]";
        return  String.format(query, dateRange, dateRange);
    }
       public static void main(String[] args) throws Exception {
        InstanceImporter remoteETLClient = new InstanceImporter("http://localhost:8080/alfresco");
        DefaultHttpClient httpclient = new DefaultHttpClient();
        UsernamePasswordCredentials creds = new UsernamePasswordCredentials("username", "password");
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), creds);
        httpclient.setCredentialsProvider(credsProvider);
        try {
                Date lastImportDate = null; // Date de dernier import
            remoteETLClient.loadEntities(remoteETLClient.buildQuery(lastImportDate), httpclient);
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
    }
 }


}

Sample REST Requests

GET List Finished Product Sample

curl --location --request GET 'https://$server/alfresco/service/becpg/remote/entity/list?query=+TYPE:"bcpg:finishedProduct"&format=json&fields=bcpg:legalName,bcpg:clients'

PARAMS

| query | +TYPE:"bcpg:finishedProduct" | | format | json | | fields | bcpg:legalName,bcpg:clients |

GET List of products by last modified Sample

curl --location --request GET 'https://$server/alfresco/service/becpg/remote/entity?format=json&query=(@cm\:created:[2020-02-10 TO MAX] OR @cm\:modified:[2020-02-10 TO MAX]) AND ( TYPE:"bcpg:finishedProduct" OR TYPE:"bcpg:semiFinishedProduct")

PARAMS

| query | (@cm\:created:[2020-02-10 TO MAX] OR @cm\:modified:[2020-02-10 TO MAX]) AND ( TYPE:"bcpg:finishedProduct" OR TYPE:"bcpg:semiFinishedProduct") | | format | json |

Get Entity allergen list Sample

curl --location --request GET 'https://$server/alfresco/service/becpg/remote/entity?format=json&query=+@bcpg\:erpCode:"TEST1"&lists=bcpg:allergenList&fields=bcpg:allergenListAllergen|bcpg:allergenCode,bcpg:allergenListVoluntary,bcpg:allergenListInVoluntary'

PARAMS

| query | @bcpg\:erpCode:"TEST1"| | format | json | | lists | bcpg:allergenList | | fields | bcpg:allergenListAllergen|bcpg:allergenCode,bcpg:allergenListVoluntary,bcpg:allergenListInVoluntary |

Get Compo List Sample

curl --location --request GET 'https://$server/alfresco/service/becpg/remote/entity?format=json&query=+@bcpg\:erpCode:"TEST1"&lists=bcpg:compoList&fields=bcpg:compoListProduct,bcpg:compoListQtySubFormula,bcpg:compoListUnit'

PARAMS

| query | @bcpg\:erpCode:"TEST1"| | format | json | | lists | bcpg:compoList | | fields | bcpg:compoListProduct,bcpg:compoListQtySubFormula,bcpg:compoListUnit |

GET Get Entity

curl --location --request GET 'https://$server/alfresco/service/becpg/remote/entity?format=json&query=+@bcpg\:erpCode:"TEST1"'

PARAMS

| query | @bcpg\:erpCode:"TEST1"| | format | json |

API Alfresco

Alfresco propose également une API REST documenté ici :

https://docs.alfresco.com/5.2/pra/1/topics/pra-welcome.html

Que vous pouvez parcourir à cette URL:

https://api-explorer.alfresco.com/api-explorer/

results matching ""

    No results matching ""